我的代码在 C 中有一个按位移位的问题,我归结为以下示例:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
int main(int argc, char **argv)
{
char a = 1;
int i=0;
uint64_t b;
for(i=0; i<64; i++)
{
b=0;
printf("i=%d\n", i);
b = (a<< ((uint64_t) i));
printf("%" PRIu64 "\n", b);
}
return 0;
}
由于在此 MWE 中不明显的原因,a
是一个 char
,我想从中生成 2 的幂,直到 2^63。它失败了,因为发生了一些奇怪的事情,因为 a
不是 uint64_t
。明显的修复是
b = ((uint64_t)a<< ((uint64_t) i))
为了理解到底发生了什么,我写了上面的 MWE 示例,我从中获得了输出(部分显示):
i=30
1073741824
i=31
18446744071562067968
i=32
1
i=33
2
现在我想知道如何解释从 i=30
到 i=31
的跳转?它是如何在 i=32
处再次变为 1 的?
如果有兴趣,我用gcc (gcc (SUSE Linux) 4.8.5
)编译了上面的代码
最佳答案
此处出现的(有点出乎意料的)规则是,当涉及到 <<
时,
the type of the result is that of the promoted left operand
这意味着 a << (uint64_t) i
的类型是一个 int
, 作为 char
输入 a
自动加宽为 int
.
看来您的 int
是一个 32 位 2 的补码类型。因此对于 i
大于或等于 31,表达式的行为是未定义。
关于c - 理解太小类型的移位操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48542911/