user3718610
user3718610

Reputation:

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

Upvotes: 1

Views: 537

Answers (3)

Joey Andres
Joey Andres

Reputation: 106

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], str1, 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.

Upvotes: 3

Jens Gustedt
Jens Gustedt

Reputation: 78903

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.

Upvotes: 1

mcleod_ideafix
mcleod_ideafix

Reputation: 11428

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.

Upvotes: 1

Related Questions