gpt4 book ai didi

c - 1U<<32 是 1,我是误解了 C 标准还是 GCC(Clang、MSVC)错误?

转载 作者:太空宇宙 更新时间:2023-11-04 05:16:24 25 4
gpt4 key购买 nike

1U << 32 有一些不同,首先将 32 分配给一个变量(例如,n)然后左移 n。我试过 printf("%u\n", 1U << 32) ,编译器会将结果优化为 0。但是当我尝试这段代码时,

#include <stdio.h>
int main() {
int n = 32;
printf("%u\n", 1U << n);
}

编译执行上面的代码会打印1的结果。

根据C/C++标准,

The value of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are zero-filled. If E1 has an unsigned type, the value of the result is E1×2^E2, reduced modulo one more than the maximum value representable in the result type. Otherwise, if E1 has a signed type and non-negative value, and E1×2^E2 is representable in the corresponding unsigned type of the result type, then that value, converted to the result type, is the resulting value; otherwise, the behavior is undefined.

在我看来,当 E1 是无符号的并且 E1 << E2 溢出时,结果将是 E1 * 2 ^ E2 mod (UINT_MAX + 1),所以 1U << n 的结果应该是 0。

但是在 x86 和 ARM 上用 GCC 4.4 到 7.2 或 Clang 3.1 到 5.0 编译得到的结果是 1。我检查了汇编代码,发现两者都产生了以下汇编,

movl   $20,-0x4(%rbp)
mov -0x4(%rbp),%eax
mov $0x1,%edx
mov %eax,%ecx
shl %cl,%edx

orr     w8, wzr, #0x1
orr w9, wzr, #0x20
stur w9, [x29, #-4]
ldur w9, [x29, #-4]
lsl w1, w8, w9

然后我检查了指令 shllsl , 关于 c9x.me我发现以下关于 shl 的描述,

The destination operand can be a register or a memory location. The count operand can be an immediate value or register CL. The count is masked to 5 bits, which limits the count range to 0 to 31.

ARM 的汇编程序指南告诉我们 lsl允许的类次是 0-31。

至少表示指令shl运行良好,这就是为什么我怀疑编译器的实现有误的原因,但似乎不可能出现如此广泛和长期的错误,有人可以向我解释一下吗?

谢谢。

最佳答案

The operands shall be of integral or unscoped enumeration type and integral promotions are performed. The type of the result is that of the promoted left operand. The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand.

C++11,§5.8 ¶1(添加了强调)

The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.

C99,§6.5.7 ¶3(添加了强调)

这些规则的制定极有可能正是因为现有平台上的轮类运算符(operator)存在这种限制;如果没有此规则,未知值的每次移位都必须转换为比简单的底层平台移位指令更复杂的代码,而移位的操作速度非常快。

关于c - 1U<<32 是 1,我是误解了 C 标准还是 GCC(Clang、MSVC)错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48489700/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com