简体   繁体   中英

Can someone explain this bitwise C code?

I don't know what's going on with this:

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

the str it's a integer and the x it's a integer pointer

Well, as mentioned, str is not an integer. It's a pointer, as it is being dereference with * operator.

*((str) + 3) is equivalent to *(str + sizeof(str[0])*3) , thus this depends on the type of str, as seen here . Same goes for other dereference operator.

So what's going on? Well, it takes the least significant 8bit of str[0], str 1 , str[2], and assemble them to one 32 bit size integer.

For instance, let W, X, Y, Z, A be arbitrary bit. Then,

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

The last 3 are shifted, 8, 16, and 24, respectively, thus,

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

Note that the least significant digits of the last 3 are replaced with 0 during the shift.

Last, they are OR'ED, which is then assigned to X,

X = AAAAAAAAZZZZZZZZYYYYYYYYXXXXXXXX

Edit: O'Ring is not as straightforward as it might seem seems W's could be anything.

Looks like str is a pointer to an array of 4 bytes, and x is a pointer to a 32 bit value. str would actually point to the first byte (LSB) of a little endian 32 bit number, and this macro would read it and store in the variable pointed by x .

Correctly written as an inline function this should look something like:

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];
}

you should use unsigned types when you do bit shifting, otherwise your result can overflow. And perhaps it also makes the idea clearer. The suposedly 8 bit of each byte are placed in the different bits of the target x .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM