对于简单的混淆分配,我需要移动unsigned int
直到它变为零。
unsigned int a = 12;
a <<= sizeof(a) * 8;
printf("%u", a);
我使用gcc test.c -o bin
编译它,GCC警告:
warning: left shift count >= width of type [-Wshift-count-overflow]
当我执行它时,它返回12
。但毫无疑问,它应该是0
。 GCC是否忽略了编译那行代码?或者我错过了什么?
答案 0 :(得分:3)
这是未定义的行为。
在任何情况下,如果右操作数的值[&lt;&lt;或&gt;&gt;]为负数或大于或等于提升左操作数中的位数,行为未定义。
(引自http://en.cppreference.com/w/cpp/language/operator_arithmetic)
此外,文章说:
<<
的带符号溢出未定义。 (自从C ++ 14以来,如果结果值可以用左类型的无符号版本表示,那么它是明确定义的。然后将tesult转换回签名。)>>
是实现定义的。 (Cppreference说,在大多数架构中,它会复制最左边的位。)<<
申请签署的否定文件未定义。这些规则对于C和C ++是相同的。以下是C11标准的相关部分:
- 对每个操作数执行整数提升。结果的类型是 升级的左操作数。如果右操作数的值为负数或
- E1的结果&lt;&lt; E2是E1左移E2位位置;腾出的位充满了 零。如果E1具有无符号类型,则结果的值为E1×2E2,模数减少 比结果类型中可表示的最大值多一个。如果E1有签名 类型和非负值,E1×2E2在结果类型中可表示,那就是 结果价值;否则,行为未定义。
- E1的结果&gt; E2是E1右移E2位位置。如果E1具有无符号类型 或者如果E1具有带符号类型和非负值,则结果的值为积分 E1 / 2E2商的一部分。如果E1有签名类型和负值,则 结果值是实现定义的。
醇>