有符号和无符号之间的减法,然后是除法

Leo*_*Lai 25 c++ unsigned arithmetic-expressions integer-overflow

以下结果让我很困惑:

int i1 = 20-80u;    // -60
int i2 = 20-80;     // -60
int i3 =(20-80u)/2; // 2147483618
int i4 =(20-80)/2;  // -30
int i5 =i1/2;       // -30
Run Code Online (Sandbox Code Playgroud)
  1. i3似乎计算为(20u-80u)/2,而不是(20-80u)/2
  2. 据说i3是一样的i5.

小智 13

IIRC,signed和unsigned int之间的算术运算将产生无符号结果.

因此,20 - 80u产生等效于的无符号结果-60:if unsigned int是32位类型,结果是4294967236.

顺便说一句,指定它以i1产生实现定义的结果,因为数字太大而不适合.获得-60是典型的,但不能保证.

  • _Incidentally,将该值分配给i1是未定义的行为_您确定吗?我教过对unsigned int的所有值都很好地定义了从unsigned int到signed int的转换. (5认同)
  • 这里没有有符号整数溢出.有转换.请参阅[conv.integral](http://eel.is/c++draft/conv.integral). (4认同)

aut*_*tic 10

int i1 = 20-80u;    // -60
Run Code Online (Sandbox Code Playgroud)

这有微妙的恶魔!操作数是不同的,因此转换是必要的.两个操作数都转换为通用类型(unsigned int在本例中为an ).结果将是一个较大的unsigned int值(比UINT_MAX + 1我的计算正确时少60 )将在int存储之前转换为i1.由于该值超出范围int,结果将是实现定义,可能是陷阱表示,因此当您尝试使用它时可能会导致未定义的行为.但是,在你的情况下它恰巧转换为-60.


int i3 =(20-80u)/2; // 2147483618
Run Code Online (Sandbox Code Playgroud)

继续从第一个例子开始,我的猜测结果20-80u将是60比UINT_MAX + 1.如果UINT_MAX是4294967295(一个共同的价值UINT_MAX),这将意味着20-80u4294967236......并4294967236 / 2为2147483618.


至于i2和其他人,应该没有意外.它们遵循传统的数学计算,没有转换,截断,溢出或其他实现定义的行为.