常量表达式中的整数溢出
integer overflow in constant expression
虽然这在 Linux 64 位 gcc 上编译得很好:
#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))
我认为实际上两者都做同样的事情,但一种方式优于另一种方式吗?
避免强制转换,这会意外地缩小 值。
备选方案 - 最好取决于很多因素。一般来说,如果数字是无符号的,附加一个 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)
虽然这在 Linux 64 位 gcc 上编译得很好:
#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))
我认为实际上两者都做同样的事情,但一种方式优于另一种方式吗?
避免强制转换,这会意外地缩小 值。
备选方案 - 最好取决于很多因素。一般来说,如果数字是无符号的,附加一个 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)