我即将改变
#define MAX_UINT16 65535
到
#define MAX_UINT16 65535UL
在许多平台上使用的大型库项目中。在使用unsigned long
文字而不是int
文字时,是否存在任何行为不同的构造(除了某些警告消失,这就是我想要更改它的原因)?
(显然没有MAX_UINT16的位移)
我正在考虑像
这样的结构unsigned long ulvar = read_something_as_unsigned_long();
uint16 ui16var;
if (ulvar > MAX_UINT16) {
display_error("Not in range\n");
ui16var = MAX_UINT16;
} else {
ui16var = ulvar;
}
编辑:当然,不需要L
,使用65535U
代替65535
时它的行为也不同吗?
答案 0 :(得分:1)
当使用无符号长文字而不是int literals时,是否存在任何行为不同的构造(除了一些警告消失,这就是我想改变它的原因)?
这里是C11(草案)标准 6.3.1.3 (强调我的)中的相关部分:
6.3.1.3有符号和无符号整数
- 当整数类型的值转换为_Bool以外的另一个整数类型时,如果该值可以用新类型表示,则它将保持不变。
- 否则,如果新类型是无符号的,则通过重复地添加或减去一个可以在新类型中表示的最大值来转换该值,直到该值在新类型的范围内。
- 否则,新类型已签名且值无法在其中表示;结果是实现定义的,或者引发实现定义的信号。
醇>
如果代码中的一个点65535U
无意中被分配给一个无法完全保存该值的有符号类型变量,则最终值是实现定义的。因此,将65535U
分配给int16_t
可以使用GCC和VC ++生成-1
,但此结果不受标准的保护,并且取决于编译器实现。此外,GCC(-Wall
)和VC ++(/W4
)默认情况下都不会发出警告;通过-pedantic
可以解决海湾合作委员会的问题。
即使它继续为65535
,也应该存在这个问题,因为它大于16位有符号2的补码类型所能容许的最大正值。所以我的建议是继续改变它。完成后,启用最大警告级别并构建项目以验证此。