C中的右左移位

R1S*_*S8K 1 c bit-manipulation

我对C中的位移进行了一个小测试,所有的位移0,8,16位都可以,我理解发生了什么.

但32位右移或左移对我来说并不清楚,我正在进行测试的变量是32位长.

然后,我改变了32位变量,这些变量将保持移位结果,但32位右左移位是相同的!

这是我的代码:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <inttypes.h>

int main() {
    uint32_t code = 0xCDBAFFEE;

    uint64_t bit32R = code >> 32;
    uint16_t bit16R = code >> 16;
    uint8_t bit8R = code >> 8;
    uint8_t bit0R = code >> 0;

    uint64_t bit32L = code << 32;
    uint16_t bit16L = code << 16;
    uint8_t bit8L = code << 8;
    uint8_t bit0L = code << 0;

    printf("Right shift:\nbit32R %.16x\nbit16R %x\nbit8R %x\nbit0R %x\n\n",
           bit32R, bit16R, bit8R, bit0R);
    printf("Left shift:\nbit32L %.16x\nbit16L %x\nbit8L %x\nbit0L %x\n\n",
           bit32L, bit16L, bit8L, bit0L);
}
Run Code Online (Sandbox Code Playgroud)

这是我得到的结果:

Right shift:
bit32R 00000000cdbaffee
bit16R 0
bit8R cdba
bit0R ff

Left shift:
bit32L 00000000cdbaffee
bit16L 0
bit8L 0
bit0L 0

Process returned 61 (0x3D)   execution time : 0.041 s
Press any key to continue.
Run Code Online (Sandbox Code Playgroud)

chq*_*lie 6

将整数右移一个等于或大于其大小的位数是不确定的行为.

C11 6.5.7按位移位算子

句法

shift-expression: additive-expression
    shift-expression << additive-expression
    shift-expression >> additive-expression
Run Code Online (Sandbox Code Playgroud)

约束

每个操作数应具有整数类型.

语义

对每个操作数执行整数提升.结果的类型是提升的左操作数的类型.如果右操作数的值为负或大于或等于提升的左操作数的宽度,则行为未定义.

结果E1 << E2E1左移位E2位置; 腾出的位用零填充.如果E1具有无符号类型,则结果的值为E1×2 E2,比结果类型中可表示的最大值减少一个模数.如果E1有一个有符号类型和非负值,并且结果类型中可以表示E1×2 E2,那么这就是结果值; 否则,行为未定义.

结果E1 >> E2E1右移位E2位置.如果E1具有无符号类型或者E1具有有符号类型和非负值,则结果的值是E1/ 2 E2的商的整数部分.如果E1具有有符号类型和负值,则结果值是实现定义的.

int您的平台上的大小似乎最多为32位,因此初始化器的行为bit32Rbit32L未定义的行为.

应该写入64位表达式:

uint64_t bit32R = (uint64_t)code >> 32;
Run Code Online (Sandbox Code Playgroud)

uint64_t bit32L = (uint64_t)code << 32;
Run Code Online (Sandbox Code Playgroud)

此外,所使用的格式printf对于传递的参数不正确(除非int有64位,这将产生不同的输出).

您的编译器似乎不完全符合C99,您应该return 0;在函数体的末尾添加最终语句main().

这是一个更正版本:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <inttypes.h>

int main(void) {
    uint32_t code = 0xCDBAFFEE;

    uint64_t bit32R = (uint64_t)code >> 32;
    uint16_t bit16R = code >> 16;
    uint8_t bit8R = code >> 8;
    uint8_t bit0R = code >> 0;

    uint64_t bit32L = (uint64_t)code << 32;
    uint16_t bit16L = code << 16;
    uint8_t bit8L = code << 8;
    uint8_t bit0L = code << 0;

    printf("Right shift:\n"
           "bit32R %.16"PRIx64"\n"
           "bit16R %"PRIx16"\n"
           "bit8R %"PRIx8"\n"
           "bit0R %"PRIx8"\n\n",
           bit32R, bit16R, bit8R, bit0R);

    printf("Left shift:\n"
           "bit32L %.16"PRIx64"\n"
           "bit16L %"PRIx16"\n"
           "bit8L %"PRIx8"\n"
           "bit0L %"PRIx8"\n\n",
           bit32L, bit16L, bit8L, bit0L);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出是:

Right shift:
bit32R 0000000000000000
bit16R cdba
bit8R ff
bit0R ee

Left shift:
bit32L cdbaffee00000000
bit16L 0
bit8L 0
bit0L ee
Run Code Online (Sandbox Code Playgroud)

这可能不是您所期望的,因为变量的类型有些不一致.