DWORD variable with low/high word and low/high byte
14,598
Solution 1
In Win32 a DWORD is a 32 bit unsigned integer. In other contexts it could possibly mean something else.
Assuminng the Win32 definition (and other Win32 typedefs):
BYTE lsb = 0x11 :
BYTE next_lsb = 0x22 :
BYTE next_msb = 0x33 :
BYTE msb = 0x44 :
DWORD dword_from_bytes = (msb << 24) | (next_msb << 16) | (next_lsb << 8) | lsb ;
dword_from_bytes
will have the value 0x44332211
.
Similarly:
WORD lsw = 0x1111 :
WORD msw = 0x2222 :
DWORD dword_from_words = (msw << 16) | lsw ;
dword_from_words
will have the value 0x22221111
.
To extract say the third byte from dword_from_bytes
for example:
next_msb = (dword_from_bytes >> 16) & 0xff ;
although the & 0xff
is not strictly necessary in this case given the type of next_msb
, but if the type of the receiver were larger than 8 bits, it will mask off the msb bits.
Solution 2
WinAPI provides macros for the manipulations of these types, such as:
Solution 3
#include <stdint.h>
#include <stdio.h>
typedef union _little_endian{
struct _word{
union _msw{
struct _msw_byte{
uint8_t MSB;
uint8_t LSB;
} __attribute__((__packed__)) MSW_BYTE;
uint16_t WORD;
} MSW;
union _lsw{
struct _lsw_byte{
uint8_t MSB;
uint8_t LSB;
} __attribute__((__packed__)) LSW_BYTE;
uint16_t WORD;
} LSW;
} __attribute__((__packed__)) WORD;
uint32_t DWORD;
} DWORD;
int main(int argc, char *argv[]){
DWORD test1;
test1.WORD.MSW.MSW_BYTE.MSB = 1;
test1.WORD.MSW.MSW_BYTE.LSB = 2;
test1.WORD.LSW.LSW_BYTE.MSB = 3;
test1.WORD.LSW.LSW_BYTE.LSB = 4;
printf("test1: hex=%x uint=%u\n", test1.DWORD, test1.DWORD);
DWORD test2;
test2.DWORD = 0x08080404;
printf("test2: hex=%x uint=%u\n", test2.DWORD, test2.DWORD);
printf("test2.WORD.MSW.MSW_BYTE.MSB: uint=%u\n", test2.WORD.MSW.MSW_BYTE.MSB);
printf("test2.WORD.MSW.MSW_BYTE.LSB: uint=%u\n", test2.WORD.MSW.MSW_BYTE.LSB);
printf("test2.WORD.LSW.LSW_BYTE.MSB: uint=%u\n", test2.WORD.LSW.LSW_BYTE.MSB);
printf("test2.WORD.LSW.LSW_BYTE.LSB: uint=%u\n", test2.WORD.LSW.LSW_BYTE.LSB);
return 0;
}
I prefer to use a combination of structs and unions.
Output:
test1: hex=4030201 uint=67305985
test2: hex=8080404 uint=134743044
test2.WORD.MSW.MSW_BYTE.MSB: uint=4
test2.WORD.MSW.MSW_BYTE.LSB: uint=4
test2.WORD.LSW.LSW_BYTE.MSB: uint=8
test2.WORD.LSW.LSW_BYTE.LSB: uint=8
Comments
-
Midas almost 2 years
How in C can we read and make
DWORD
variables with a low and high word and low and high byte? -
Midas over 13 yearsNow it starts to make sense. But what does the
<<
,>>
and|
actually mean? Thanks! -
valdo over 13 yearsIt's better to use the dedicated macros, such as
HIWORD
,LOWORD
,MAKELONG
and etc. Because different processors use different byte ordering (little/big endian and etc.) -
Midas over 13 yearsWell, never mind. I have read the docs about bitwise operators and I understand how it works now!
-
Clifford over 13 years@valdo: While I agree that the API defined macros should be used, byte ordering is not the issue;
(msw << 16)
for example will always place a value in the high-order word regardless of endian-ness. There are other macros for exchanging data between machines of differing endian-ness. What they do do is encapsulate the knowledge of API defined word sizes to ensure consistency and avoid errors. -
Hanan N. over 10 yearsin addition you have the
HIBYTE
andLOBYTE
respectively -
Laurie Stearn over 2 yearsMS = Most Significant, LS = Least Significant. Thanks. :)