views:

230

answers:

6

I have a DWORD value that in Hex might look like:

DWORD Val = 0xFF01091A

How can I read each byte? What I mean is, how can I read FF, 01, 09 and 1A?

Thanks!

+2  A: 
DWORD x1 = (0xFF01091A & 0xFF000000) >> 24;
DWORD x2 = (0xFF01091A & 0x00FF0000) >> 16;
DWORD x3 = (0xFF01091A & 0x0000FF00) >> 8;
DWORD x4 = (0xFF01091A & 0x000000FF) >> 0;
AraK
Straight-up old school!
pianoman
That wouldn't give the right result, though; it'd return 0xFF000000, 0x00FF0000, 0x0000FF00, and 0x000000FF. You need to bit-shift the values as well, so x1 >>= 24, x2 >>= 16, and x3 >>= 8.
JAB
You should L-Shift by 24, 16, 8, and 0 bits.
Kennet Belenky
right :) I didn't write the shifts
AraK
Oops... R-Shift.
Kennet Belenky
thanks all. So example code would help.
wonderer
+5  A: 
DWORD value;
// casts to `char *` are always ok:
unsigned char * bytes = (unsigned char *)&value;
unsigned char third_byte = bytes[2];

Keep in mind that this will get the bytes as they are placed in memory: On little-endian machines bytes[0] will hold the least significant byte, on big-endian machines it'll hold the most significant one.

If you want to get the bytes by significance, use shifting as suggested in Efraim's answer.

Christoph
Nice and simple, but has different behavior on little endian and big endian systems. I don't think that was the intention.
Thorarin
@Thorarin: added comment about endianness
Christoph
+1  A: 

AraK's way works. An other way you can do it is:

char x1 = *(((char*)&Val) + 0);
char x2 = *(((char*)&Val) + 1);
char x3 = *(((char*)&Val) + 2);
char x4 = *(((char*)&Val) + 3);

Watch out though, this way will be sensitive to the endian-ness of the machine.

Kennet Belenky
+8  A: 

Not really its more like:

uint8_t Byte1 = (Val>> 0) & 0xFF;
uint8_t Byte2 = (Val>> 8) & 0xFF;
uint8_t Byte3 = (Val>>16) & 0xFF;
uint8_t Byte4 = (Val>>24) & 0xFF;
EFraim
Yes, the shift is needed to get the correct result +1
Ed Swangren
hope you don't mind me fixing the formatting
Christoph
your way is actually cleaner :)
AraK
Dipstick
+1  A: 

Mask and shift (as suggested in a previous answer) works; a somewhat trickier alternative is "pointer type punning", i.e.

xlowbyte = (unsigned char*)(&Val) [0]; /* LSB, 0x1A */
xmidlowb = (unsigned char*)(&Val) [1]; /* 2nd-LSB, 0x09 */

etc -- assuming you're on a little-endian machine (which is likely if you use Windows).

Alex Martelli
+2  A: 

Use a union:

union Bytes {
    char c[4];
    unsigned int n;
};

int main() {
    Bytes b;
    b.n = 0xFF01091A;
    char c = b.c[2];
}

Edit: Sorry, this is C++ code. I'm too tired to convert it to C and test it, but you get the idea?

anon
not much conversion to be done: there's a `union` missing before `Bytes b;` and you should declare `main` as `int main(void)`
Christoph