关于无符号整数下溢的C行为的问题
我在很多地方读到过,无符号整数溢出在C中定义得很好,与有符号溢出不同 底流是否相同 例如:关于无符号整数下溢的C行为的问题,c,integer,types,integer-overflow,underflow,C,Integer,Types,Integer Overflow,Underflow,我在很多地方读到过,无符号整数溢出在C中定义得很好,与有符号溢出不同 底流是否相同 例如: unsigned int x = -1; // Does x == UINT_MAX? 谢谢 我记不起在哪里了,但我在某处读到,无符号整数类型的算术是模的,所以如果是这样的话,那么-1==UINT_MAX mod(UINT_MAX+1)。-1,当表示为2的补码时,等于0xFF…F,表示数字的位数。在无符号数字空间中,该值为可能的最大值(即所有位均已设置)。因此,x==UINT_MAX。以下代码在C99严
unsigned int x = -1; // Does x == UINT_MAX?
谢谢
我记不起在哪里了,但我在某处读到,无符号整数类型的算术是模的,所以如果是这样的话,那么-1==UINT_MAX mod(UINT_MAX+1)。-1,当表示为2的补码时,等于0xFF…F,表示数字的位数。在无符号数字空间中,该值为可能的最大值(即所有位均已设置)。因此,x==UINT_MAX。以下代码在C99严格编译器上发出“1”:
#include <stdio.h>
#include <stdint.h>
#include <limits.h>
int main(int argc, char **argv){
uint32_t x = -1;
printf("%d", x == UINT_MAX ? 1 : 0);
return 0;
}
#包括
#包括
#包括
int main(int argc,字符**argv){
uint32_t x=-1;
printf(“%d”,x==UINT_MAX?1:0);
返回0;
}
您正在混合有符号和无符号数字,这是不酷的
unsigned int x = 0u - 1u; // is OK though
§6.2.5,第9段:
涉及无符号的计算
操作数永远不会溢出,因为
无法用表示的结果
生成的无符号整数类型为
一个数的约化模
大于指定的最大值
可以由结果
类型
编辑:
抱歉,引用错误,但结果仍被锁定。正确的参考是§6.3.1.3(有符号和无符号整数转换):
如果新类型是
无符号,则该值由
反复地加或减一
超过可以使用的最大值
以新类型表示,直到
该值在新值的范围内
类型
是的,
x==UINT\u MAX
我认为术语“下溢”只适用于浮点数,其中不能表示一些非常接近零的数字。整数不会有这个问题。@bde我同意这是一个技术上准确的说法,但由于违反了数字系统底部的边界条件,这个术语经常被重载。标准是否要求两个S补码?否,标准不要求两个S补码,所以这个解法不是通用的;参见我的答案。不要求uint32_t
beUINT_MAX
-UINT_MAX
的最大值可以小到65535,大到ULONG_MAX
。如果将uint32\u t
更改为unsigned
则正确。在n位无符号存储空间中存储负数X需要存储与X mod 2一致的最小非负数ⁿ. 因为任意两个的补位有符号数Y的位模式将对无符号值Y或Y+2进行编码ⁿ, 两者都是mod 2全等的ⁿ, 其中一个是最小的非负数,与mod 2全等ⁿ, 这意味着两个补数遵循无符号整数的行为,而不是相反。它可能不酷,也可能不酷,但它是定义得很好的符合标准的C。@Stephen Canon,不正确。未定义-1的按位表示。例如,它可能是一个补语。@Stepen,“标准一致”可能是,但“定义良好”?这是问题的症结所在,-1(或任何有符号整数)的位表示法不在其中。§6.3.1.3规定了行为。谢谢,斯蒂芬,你说得对。不过,林特更喜欢我的解决方案您的引用很好,但不适用,因为表达式-1涉及有符号操作数,而不是无符号操作数。问题已经承认溢出定义良好。问题是关于负数,而不是正数。@Doug,@Mark:问题是关于从有符号整数到无符号整数的转换,§6.3.1.3.+1规定了正确答案,§6.3.1.3似乎是要求(无符号整数)(-1)的一种非常扭曲的方式==UINT_MAX
不一定需要有符号的数字才能使用2的补码。@Stephen,感谢您的坚持(以及对6.3.1.3的挖掘);我被纠正了。接受的答案“数字的内部表示形式不变”太糟糕了