常量表达式中的整数溢出

时间:2016-03-29 23:40:36

标签: c avr-gcc

虽然使用gcc在Linux 64位上编译良好:

#define CONST_1 255
#define CONST_2 255

#define CONST_PROD ((CONST_1) * (CONST_2))

它在avr-gcc(8位)上发出溢出警告:

constants.c:13:31: warning: integer overflow in expression [-Woverflow]
 #define CONST_PROD ((CONST_1) * (CONST_2))
                               ^

这是公平的,因为结果对于16位有符号整数来说太大了。

在定义这样的常数时警告会消失:

#define CONST_1 255U

或添加演员:

#define CONST_PROD ((uint16_t)(CONST_1) * (CONST_2))

我认为实际上两者都做同样的事情但是比另一种方式更受欢迎?

1 个答案:

答案 0 :(得分:1)

避免施放,这可能意外地缩小值。

替代品 - 最好取决于许多事情。一般情况下,如果数字是无符号的,请附加u或使用某些UINTN_C()

 // u or U the same
 #define CONST_1 255U
 #define CONST_1 255u

 // 1u* to bring about unsigned math.  () around `CONST_1` shouldn't be necessary.
 #define CONST_PROD (1u*CONST_1 * CONST_2)

 // Macros for minimum-width integer constants
 #include <stdint.h>
 // UINT16_C() makes the constant type uint_least16_t
 #define CONST_PROD (UINT16_C(CONST_1) * UINT16_C(CONST_2))

OTOH,如果一个值是精确的N位而没有其他宽度,

 #define CONST16_MASK_MIDDLE_BITS  ((uint16_t) 0x00FFFF00u)

我认为UL没什么价值。如果你想要常数是一个宽类型,那就选择最宽的。

 #define CONST_1 255ULL
 // or 
 #define CONST_1 ((uintmax_t)255u)