zorleone Asked: 2024-01-29 22:59:23 +0800 CST2024-01-29 22:59:23 +0800 CST 2024-01-29 22:59:23 +0800 CST C23 字节顺序宏可用于确定位字段的布局吗? 772 我一直在阅读有关 C 标准的新增内容,并且遇到过用于确定编译时字节序的宏。 然而该标准仍然规定 单元内位字段的分配顺序(高位到低位或低位到高位)是 实现定义的。 这是否意味着位字段的布局可以是任意的,无论 的值如何__STDC_ENDIAN_NATIVE__? c 4 个回答 Voted KamilCuk 2024-01-29T23:06:52+08:002024-01-29T23:06:52+08:00 C23 字节顺序宏可用于确定位字段的布局吗? 不 这是否意味着位字段的布局可以是任意的,无论 的值如何__STDC_ENDIAN_NATIVE__? 是的。 字节字节序(字内字节的顺序)和位字节序(字节内位的顺序)是分开的。 gulpr 2024-01-29T23:10:17+08:002024-01-29T23:10:17+08:00 Endianess 仅适用于较长类型中的字节顺序。 位域中的位顺序与字节序没有任何共同点。 Best Answer Lundin 2024-01-30T00:08:08+08:002024-01-30T00:08:08+08:00 位顺序首先并不取决于字节顺序。相反,如果结构中的第一位被视为 MSB 或 LSB。例如,某些特定于实现的位字段可能只有 1 字节大。 根据常识,我认为第一位应该是 MSB,因为除了 IBM 之外,每个人都是这样枚举位的,从最高到最低(7 到 0)。但显然大多数实现都将其作为 LSB。你可以尝试这个例子: #include <stdio.h> typedef struct { unsigned bit:1; } bit_t; int main (void) { bit_t bit = { .bit=1 }; unsigned char* byte = (unsigned char*)&bit; if(*byte & 0x01) { puts("bit = LSB"); } else if(*byte & 0x80) { puts("bit = MSB"); } else { puts("Completely broken compiler.") } } 我在编译器资源管理器上尝试了各种目标: 位 = 最低有效位: x86_64(gcc/clang/icc/msvc) ARM32(海湾合作委员会) ARM64(海湾合作委员会) Power64le(叮当声) AVR(海湾合作委员会) 位=最高有效位: MIPS64(gcc/clang) 电源(海湾合作委员会) Ian Abbott 2024-01-30T01:44:18+08:002024-01-30T01:44:18+08:00 可寻址存储单元内位域成员的字节顺序和放置顺序均由实现定义,但相互独立。 注 1:在下面的 ASCII 艺术图中,可寻址存储单元内的位数、位字段成员(或填充)或字节已垂直写入。例如: 2 3 指示位 23 的位置。 注2:在小端图中,位数从左到右递增。在大端图中,位数从右向左递增。 考虑以下类型,在单个 32 位宽、4 字节可寻址存储单元中具有两个大小为 20 位和 12 位的位字段: struct { unsigned foo:20; unsigned bar:12; }; 有四种字节序/存储可能性: Little-endian,从可寻址存储单元的位 0 向上打包: | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +---------------------------------------------------------------+ | Addressable Storage Unit (32 bits) | |0 0 0 1 1 1 2 2 2 3| |0 7 8 5 6 9 0 3 4 1| +---------------+---------------+---------------+---------------+ | Byte 0 | Byte 1 | Byte 2 | Byte 3 | |0 7|0 7|0 3 4 7|0 7| +---------------+---------------+-------+-------+---------------+ | foo (20 bits) | bar (12 bits) | |0 0 0 1 1 1|0 0 0 1| |0 7 8 5 6 9|0 3 4 1| +---------------------------------------+-----------------------+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Little-endian,从可寻址存储单元的第 31 位向下打包: | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +---------------------------------------------------------------+ | Addressable Storage Unit (32 bits) | |0 0 0 1 1 1 1 2 2 3| |0 7 8 1 2 5 6 3 4 1| +---------------+---------------+---------------+---------------+ | Byte 0 | Byte 1 | Byte 2 | Byte 3 | |0 7|0 3 4 7|0 7|0 7| +---------------+-------+-------+---------------+---------------+ | bar (12 bits) | foo (20 bits) | |0 0 0 1|0 0 0 1 1 1| |0 7 8 1|0 3 4 1 2 9| +-----------------------+---------------------------------------+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 大尾数法,从可寻址存储单元的位 0 向上打包: | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +---------------------------------------------------------------+ | Addressable Storage Unit (32 bits) | |3 2 2 2 1 1 1 0 0 0| |1 4 3 0 9 6 5 8 7 0| +---------------+---------------+---------------+---------------+ | Byte 0 | Byte 1 | Byte 2 | Byte 3 | |7 0|7 4 3 0|7 0|7 0| +---------------+-------+-------+---------------+---------------+ | bar (12 bits) | foo (20 bits) | |1 0 0 0|1 1 1 0 0 0| |1 4 3 0|9 6 5 8 7 0| +-----------------------+---------------------------------------+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 大尾数法,从可寻址存储单元的第 31 位向下打包: | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +---------------------------------------------------------------+ | Addressable Storage Unit (32 bits) | |3 2 2 1 1 1 1 0 0 0| |1 4 3 6 5 2 1 8 7 0| +---------------+---------------+---------------+---------------+ | Byte 0 | Byte 1 | Byte 2 | Byte 3 | |7 0|7 0|7 4 3 0|7 0| +---------------+---------------+-------+-----------------------+ | foo (20 bits) | bar (12 bits) | |1 1 1 0 0 0|1 0 0 0| |9 2 1 4 3 0|1 8 7 0| +---------------------------------------+-----------------------+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
不
是的。
字节字节序(字内字节的顺序)和位字节序(字节内位的顺序)是分开的。
Endianess 仅适用于较长类型中的字节顺序。
位域中的位顺序与字节序没有任何共同点。
位顺序首先并不取决于字节顺序。相反,如果结构中的第一位被视为 MSB 或 LSB。例如,某些特定于实现的位字段可能只有 1 字节大。
根据常识,我认为第一位应该是 MSB,因为除了 IBM 之外,每个人都是这样枚举位的,从最高到最低(7 到 0)。但显然大多数实现都将其作为 LSB。你可以尝试这个例子:
我在编译器资源管理器上尝试了各种目标:
位 = 最低有效位:
位=最高有效位:
可寻址存储单元内位域成员的字节顺序和放置顺序均由实现定义,但相互独立。
注 1:在下面的 ASCII 艺术图中,可寻址存储单元内的位数、位字段成员(或填充)或字节已垂直写入。例如:
指示位 23 的位置。
注2:在小端图中,位数从左到右递增。在大端图中,位数从右向左递增。
考虑以下类型,在单个 32 位宽、4 字节可寻址存储单元中具有两个大小为 20 位和 12 位的位字段:
有四种字节序/存储可能性:
Little-endian,从可寻址存储单元的位 0 向上打包:
Little-endian,从可寻址存储单元的第 31 位向下打包:
大尾数法,从可寻址存储单元的位 0 向上打包:
大尾数法,从可寻址存储单元的第 31 位向下打包: