我有一个复杂的定点运算程序.
似乎偶尔有溢出.
为了找到它们,我设置了旗帜-ftrapv.这似乎只适用于int32_t.那是对的吗?
有没有办法用int16_t和实现相同的行为int8_t?
这是我的测试代码:
#include <stdio.h>
#include <stdint.h>
int main(void)
{
int8_t int8 = 127;
int8 += 1;
printf("int8: %d\n",int8);
int16_t int16 = 32767;
int16 += 1;
printf("int16: %d\n",int16);
int32_t int32 = 2147483647;
int32 += 1;
printf("int32: %d\n",int32);
}
Run Code Online (Sandbox Code Playgroud)
我编译:
rm a.out; gcc -ftrapv main.c && ./a.out
Run Code Online (Sandbox Code Playgroud)
得到:
int8: -128
int16: -32768
Aborted
Run Code Online (Sandbox Code Playgroud)
我的编译器版本是gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609.
注意:有些答案是指我之前错误编写的测试程序.
我不知道你想做什么.
int8_t可以容纳的最大值是127而不是 255.int16_t是32767而不是 65535.int32_t可以容纳的最大值确实是2147483647.所以这就是你的代码所做的:
int8_t int8 = 255;将值255分配给最多可容纳127的变量.它不适合,以某种实现定义的方式调用隐式转换.最有可能的是你得到的值为-1.这是一个隐式左值转换,没有有符号整数溢出.
printf("int8: %d\n",int8 + 1);打印结果-1 + 1.是的0.没有任何溢出.
同样的事情发生在16位变量,隐式转换,最终值为-1,打印0.
int32_t int32 = 2147483647;此行与其他两行不同,因为您实际上将int32设置为它可以包含的最大值.如果你采取+1这种做法,你会得到一个有符号的整数溢出,它会调用未定义的行为.
最重要的是,两个较小的整数类型在添加时不会溢出,即使这是您的代码正在做的事情(它没有).两个操作数都会将整数提升为类型int- 不会有溢出.有关其工作原理的详细说明,请参阅隐式类型提升规则.
我不这么认为,因为C的默认整数提升规则,算法确实不会发生在较小的类型中.
例如(来自C11草案,§5.1.2.311):
示例2
在执行片段时Run Code Online (Sandbox Code Playgroud)char c1, c2; /* ... */ c1 = c1 + c2;"整数提升"要求抽象机器将每个变量的值提升为
int大小,然后添加两个ints并截断总和.
这常常是代码混淆的原因,例如:
uint8_t x;
x = get_some_byte();
x |= 1;
Run Code Online (Sandbox Code Playgroud)
最后一行实际上相当于:
x = x | 1;
Run Code Online (Sandbox Code Playgroud)
并且右侧将被提升为int,因此分配"回到" uint8_t风险截断,一些工具警告你.
| 归档时间: |
|
| 查看次数: |
532 次 |
| 最近记录: |