开发者

How to decipher 4 short vars from a long var using bit manipulations in C++?

long wxyz; //(w = bits 0-8, x = bits 9-17 , y = bits 18-23, z =  bits 24-29)


short w;

short x;开发者_开发技巧

short y;

short z;

w= wxyz & 0xFF800000;
x= wxyz & 0x007FC000;
y= wxyz & 0x00003F00;
z= wxyz & 0x000000FC;

Is this code correct?

Thanks


You need to shift the bits down.

w= (wxyz & 0xFF800000) >> 23;
x= (wxyz & 0x007FC000) >> 14;
y= (wxyz & 0x00003F00) >> 8;
z= (wxyz & 0x000000FC) >> 2;


You should do the following to get the highest byte from the 4 bytes int w = (wxyz & 0xFF000000) >> 24. First apply bit mask and then shift bits to the lowest byte.

Or you can do it other way around - shift, apply bitmask:

w = (wxyz >> 24) & 0xFF
x = (wxyz >> 16) & 0xFF
y = (wxyz >> 8) & 0xFF
z = wxyz & 0xFF

But isn't it easier to use unions?


w =  wxyz & 0x000001ff;
x = (wxyz & 0x0003fe00) >> 9;
y = (wxyz & 0x00fc0000) >> 17;
z = (wxyz & 0x3f000000) >> 23;

Edit: need to cast long to short to avoid compiler warning:

w = (short) wxyz & 0x000001ff;
x = (short) ((wxyz & 0x0003fe00) >> 9);
y = (short) ((wxyz & 0x00fc0000) >> 17);
z = (short) ((wxyz & 0x3f000000) >> 23);


Hold on -- what do you mean by bits 0-8? This usually means the nine least significant bits, in which case you've grasped the wrong end of the int.


This is the way I prefer to handle this, by "inching". It just makes more sense in my head. Also, unlike a mask and then shift, there is no problem of a >> being sign-extending (C/C++ isn't Java or C# in well-definedness there). I am going with the assumption that 0 is the MSB (and there are 32bits total, although a long can be more), as stated in the question.

long wxyz = ...; //(w = bits 0-8, x = bits 9-17 , y = bits 18-23, z =  bits 24-29)

wxyz >>= 2; // discard 30-31 (or, really, "least two insignificant")

z = wzyz & 0x3f; // easy to see this is "6 bits", no?
wzyz >>= 6; // throw them out

y = wzyz & 0x3f;
wzyz >>= 6;

x = wzyz & 0x1ff;
wzyz >>= 9;

w = wzyz & 0x1ff;
wzyz >>= 9; // for fun, but nothing consumes after

P.S. Adjusting for types is left as an exercise to the reader.


Here's a different solution you can use.

long wxyz;
short w, x, y, z;
char* buf = new char[sizeof(long)];
buf = (char*)long; // cast long as byte array
w = (short)buf[0]; // The way you sort depends on endianness
x = (short)buf[1];
y = (short)buf[2];
z = (short)buf[3];
delete[] buf;


Partially correct. You'll have to shift them to the right if you want the values of each segment.

short w = (short)((wxyz & 0xFF800000) >> 23);
short x = (short)((wxyz & 0x007FC000) >> 14);
short y = (short)((wxyz & 0x00003F00) >> 8);
short z = (short)((wxyz & 0x000000FC) >> 2);

These are correct values.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜