Sim*_*mer 7 c++ types casting integer-promotion c++11
作为" /sf/ask/2361242901/ " 的后续行动
我问自己,如果促进所有类型(除了一些例外),以较低的排名比int来int进行算术运算可能导致UB在某些情况下.
例如:
unsigned short a = 0xFFFF;
unsigned short b = a*a;
Run Code Online (Sandbox Code Playgroud)
由于unsigned short被提升为int算术运算,这将导致:
unsigned short a = 0xFFFF;
unsigned short b = (int)a*(int)a;
Run Code Online (Sandbox Code Playgroud)
因为(int)0xFFFF*(int)0xFFFF导致溢出,并且有符号类型的溢出是UB:可以将两个无符号短路相乘x,y导致未定义的行为x*y > INT_MAX
更新:
该问题专门针对的int是32位且short为16位的情况.
C++11§3.9.1/ 4,完整报价:
"声明的无符号整数
unsigned应遵守算术模2 n的定律,其中n是该特定整数大小的值表示中的位数.
除了关于"声明unsigned" 的略微误导的措辞之外,这似乎适用于每个只涉及某些给定无符号类型的参数的算术表达式,将产生该模型的模2 n的结果.
但是,对于低转换级别的无符号类型,根本没有算术表达式int:明显此类表达式中的所有参数至少转换为(1)int,或者取决于C++实现的数字范围,最多为unsigned int.
因此,a*b在哪里a和b是unsigned short值,(2)可以有正式的未定义行为.因为它不是unsigned short表达.它(在实践中)是一种int表达方式.
也就是说,使用合理的编译器,它不会引入特殊的外壳,它会注意到正式的UB,并且实际上有8位字节和unsigned short最大值可以表示int,并且通用二进制补码有符号整数表示,结果,当转换回来时下来unsigned short,就好像是模数运算一样unsigned short.这是因为在机器代码级别,两个补码只是模数运算,范围以0为中心.
(1)在实践中,通常会使用每字节8位的实现,其中最大值unsigned short恰好在该int范围内,因此在实践中我们正在讨论转换为int.
(2)例如,对于16位unsigned short和32位int,(2 16 -1)2 = 2 32 -2×2 16 +1> 2 31 -1,其中最后一个值是最大正值int.