有人可以解释这个按位的 C 代码吗?

Can someone explain this bitwise C code?

我不知道这是怎么回事:

#define _PACK32(str, x)                   \
    {                                             \
        *(x) =   ((int) *((str) + 3)      )    \
               | ((int) *((str) + 2) <<  8)    \
               | ((int) *((str) + 1) << 16)    \
               | ((int) *((str) + 0) << 24);   \
    }

str是整数,x是整数指针

看起来 str 是指向 4 字节数组的指针,而 x 是指向 32 位值的指针。 str 实际上指向一个 little endian 32 位数字的第一个字节 (LSB),这个宏将读取它并存储在 x.

指向的变量中

嗯,如前所述,str 不是整数。它是一个指针,因为它被 * 运算符取消引用。

*((str) + 3) 等同于 *(str + sizeof(str[0])*3),因此这取决于 str 的类型,如 here 所示。其他取消引用运算符也是如此。

所以这是怎么回事?好吧,它将 str[0]、str1、str[2] 和 assemble 的最低有效 8 位取为一个 32 位大小的整数。

例如,设W, X, Y, Z, A为任意位。那么,

  • *(str + 3) = WWWWWWWWWWWWWWWWWWWWWWWWXXXXXXXX
  • *(str + 2) = WWWWWWWWWWWWWWWWWWWWWWWWYYYYYYYY
  • *(str + 1) = WWWWWWWWWWWWWWWWWWWWWWWWZZZZZZZZ
  • *(str + 0) = WWWWWWWWWWWWWWWWWWWWWWWWAAAAAAAA

后3位分别移动8位、16位、24位,因此,

  • *(str + 3) = WWWWWWWWWWWWWWWWWWWWWWWWXXXXXXXX
  • *(str + 2) = WWWWWWWWWWWWWWWWYYYYYYYY00000000
  • *(str + 1) = WWWWWWWWZZZZZZZZ0000000000000000
  • *(str + 0) = AAAAAAAA000000000000000000000000

请注意,最后3位的最低有效位在移位过程中被替换为0。

最后,它们是OR'ED,然后赋值给X,

X = AAAAAAAAZZZZZZZZYYYYYYYYXXXXXXXX

编辑: O'Ring 并不像看起来那么简单 W's 可以是任何东西。

正确地写成一个 inline 函数,它应该类似于:

void pack32(void const*p, unsigned* x) {
    unsigned char const* str = p;
     *x = str[0];
     *X = *x<<8 | str[1];
     *X = *x<<8 | str[2];
     *X = *x<<8 | str[3];
}

进行位移时应使用无符号类型,否则结果可能会溢出。也许它也让想法更清晰。每个字节的 8 位被放置在目标 x.

的不同位中