int16_t和int8_t的Fixpoint-Overflow-Traps

时间:2017-09-12 08:52:46

标签: c ubuntu gcc

我有一个复杂的定点运算程序。

似乎偶尔有溢出。

为了找到它们,我设置了标志-ftrapv。这似乎仅适用于int32_t。那是对的吗?

有没有办法与int16_tint8_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);
}

我编译:

rm a.out; gcc -ftrapv main.c && ./a.out

并获得:

int8: -128
int16: -32768
Aborted

我的编译器版本是gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609

注意:有些答案涉及我之前写错误的测试程序。

3 个答案:

答案 0 :(得分:6)

我不知道你要做什么。

  • 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 - 不会有溢出。有关其工作原理的详细说明,请参阅Implicit type promotion rules

答案 1 :(得分:5)

我不这么认为,因为C的默认整数提升规则,算法确实不会发生在较小的类型中。

例如(来自C11草案,§5.1.2.311):

  

例2   在执行片段时

char c1, c2;
/* ... */
c1 = c1 + c2;
     

“整数促销”要求抽象机推广   每个变量的值为int大小,然后添加两个int和   截断总和。

这常常是代码混淆的原因,如:

uint8_t x;

x = get_some_byte();
x |= 1;

最后一行实际上相当于:

x = x | 1;

并且右侧将被提升为int,因此“返回”uint8_t的分配可能会截断某些工具警告您的内容。

答案 2 :(得分:-1)

我为自己找到了以下微创方法:

#include <stdio.h>
#include <stdint.h>

#ifdef INTOF_CHECK
#define INTOF_ERROR (printf("line %d: loss of bits\n", __LINE__) & 0)
#define i8(v) ((v) > 127 || (v) < -127 ? INTOF_ERROR : (v))
#define i16(v) ((v) > 32767 || (v) < -32768 ? INTOF_ERROR : (v))
#else
#define i8(v) (v)
#define i16(v) (v)
#endif

int main(void)
{  
    int8_t int8 = i8(127);
    printf("int8: %d\n",i8(int8 + 1));

    int16_t int16 = i16(32767);
    printf("int16: %d\n",i16(int16 + 1));
}

编译:

rm -f a.out; gcc main.c -DINTOF_CHECK && ./a.out

输出结果为:

line 16: loss of bits
int8: 0
line 19: loss of bits
int16: 0