【发布时间】:2023-03-27 04:19:02
【问题描述】:
2011 年草案说:
6.5.7 移位运算符/4 E1
和
J.2 未定义的行为 表达式移动负数或移动量大于或等于 提升表达 (6.5.7)。
如何解释两者? J.2 是否指所有移位(无符号或无符号)或在第 6.5.7 节中明确提到的 UB(仅适用于有符号)。
我的意思是,unsigned int i=...; i <<= sizeof(i)*CHAR_BIT;UB?
【问题讨论】:
-
J.2 指所有移位,结果未定义。一些实现选择评估
(uint32_t)x << 32到x,一些评估到0。也许42会很好;) -
@Jean-BaptisteYunès 不,
char可以有超过 8 位 并且unsigned int允许有填充位。跨度> -
@Jean-BaptisteYunès 好吧,大多数 机器,但是在具体询问 UB 时这有什么帮助? ;)
-
即使你想通过使用可变的移位次数来“欺骗”它 -
val <<= shift;它将被转换为:x86shl eax,clx64shl rax,cl并且那些机器代码指令可以不要移动 32 或 64 次,因为第一个只需要 5 位,第二个 6 位来自 cl 寄存器。因此 val 将在移位后保持其初始值。 -
x86 也有不同的化身。原来的 8086/8088确实移动了
CL给出的全部位数。因此,如果您有一台 PC/XT 和一台 PC/AT,您可以从同一个可执行文件中得到不同的结果。 UB 的另一个原因。
标签: c language-lawyer