带符号 int 的位移位重置过多

geo*_*hei 5 c unsigned bit-shift

请看下面的代码片段,它基本上只是将 1 个字节向左移动 24 位。

uint64_t i = 0xFFFFFFFF00000000;
printf("before: %016llX \n", i);
i += 0xFF << 24;
printf("after : %016llX \n", i);

// gives:
// before: FFFFFFFF00000000
// after : FFFFFFFEFF000000
Run Code Online (Sandbox Code Playgroud)

最重要的 32 位是FFFFFFFEE在最后观看)。这并不像我预期的那样。我不明白为什么左移 1 个字节 24 位会触及位 #32(位 #31 应该是最后一个修改的)它把最后一个F( 1111) 变成了E( 1110) 。

为了使其正常工作,我使用了0xFF无符号 ( 0xFFU)。

uint64_t i = 0xFFFFFFFF00000000;
printf("before: %016llX \n", i);
i += 0xFFU << 24;
printf("after : %016llX \n", i);

// gives:
// before: FFFFFFFF00000000
// after : FFFFFFFFFF000000
Run Code Online (Sandbox Code Playgroud)

为什么带符号 int ( 0xFF) 的位移位会过多地触摸/重置一位?

dbu*_*ush 3

您左移到符号位。

\n

整数常量的0xFF类型为int。假设 anint是 32 位,则表达式0xFF << 24将设置为 1 的位移入有符号整数的高位会触发未定义的行为,在您的情况下,该行为表现为意外值。

\n

C 标准第 6.5.7p4 节对此进行了详细说明

\n
\n

的结果E1 << E2E1左移位E2位置;空出的位用零填充。如果E1具有无符号类型,则结果的值为 E1\xc3\x972 E2,比结果类型中可表示的最大值减少模一。如果E1具有有符号类型和非负值,且 E1\xc3\x972 E2可在结果类型中表示,则这就是结果值;否则,行为是未定义的。

\n
\n

通过使用U后缀,这使得常量具有类型unsigned int,并且将设置为 1 的位移入高位是有效的,因为没有符号位。

\n