c-获取单词中字节地址的最安全的跨平台方法是什么



下面在big-endian上将byte设置为1,在little-endian上设置为0。

uint16_t word = 0x0001;
uint8_t byte = *(((uint8_t *)&word) + 1);

有没有任何方法可以获得跨平台安全的低字节或高字节地址?

自C99以来,代码可以使用复合文字来查找MSByte地址偏移量
让编译器形成高效的代码。

下面使用一个4字节的示例来帮助说明遵守big、little和PDP endian。

int main() {
uint32_t word = 0x12345678;
printf("%pn", (void*)&word);
for (unsigned i=0; i<sizeof word; i++) printf("%xn", ((uint8_t*) &word)[i]);
uint8_t *msbyte_address = ((uint8_t*) &word) + //
//  v----------------------------------------------------v compound literal
( union { uint32_t u32; uint8_t u8[4]; }) {0x00010203}.u8[0];
//                                    value at 1st byte    ^---^
printf("%pn", (void*)msbyte_address);
}

示例输出(小端(

0xffffcbfc
78
56
34
12
0xffffcbff

对于uint16_t

uint16_t word = 0x1234;
uint8_t *msbyte_address = ((uint8_t*) &word) + 
( union { uint16_t u16; uint8_t u8[2]; }) {0x0001}.u8[0];

可能是这样的:

int isBigEndian()
{
uint16_t word = 0x0001;
return *(((uint8_t *)&word) + 1);
}
void main()
{
uint16_t word = 0x0001;
uint8_t byte = *(((uint8_t *)&word) + isBigEndian());
printf("%dn", byte);
}

为了避免每次都在运行时进行检查,可以使用#define并使用assert验证它是正确的假设。像这样:

#define BIG_ENDIAN 0  // 0 or 1 depending on what the platform is
void main()
{
assert(isBigEndian() == BIG_ENDIAN);  // Make sure #define is OK
// more code...
}

在代码的其他地方,您可以根据平台使用符号BIG_ENDIAN来编译代码。因此,除了assert之外,没有其他实际检查。

最新更新