关于无符号整数下溢的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严

我在很多地方读到过,无符号整数溢出在C中定义得很好,与有符号溢出不同

底流是否相同

例如:

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
be
UINT_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的挖掘);我被纠正了。接受的答案“数字的内部表示形式不变”太糟糕了