我遇到了一些具有联合的代码(它位于 Microchip 的库中)。
一切都很好,直到我看到它为联盟的不同成员依次分配了值。我的第一反应是“他们正在写相同的位置......”然后我决定做一个测试。根据我认为我理解的每一种衡量标准,这个联合应该是一个字节(8 位)。但它不是...它是 4 个字节。
#pragma pack(1)
typedef union _STATUS
{
BYTE Val;
struct {
unsigned BC8 : 1;
unsigned BC9 : 1;
unsigned BSTALL : 1;
unsigned DTSEN : 1;
unsigned INCDIS : 1;
unsigned KEN : 1;
unsigned DTS : 1;
unsigned UOWN : 1;
};
struct {
unsigned BC8 : 1;
unsigned BC9 : 1;
unsigned PID0 : 1;
unsigned PID1 : 1;
unsigned PID2 : 1;
unsigned PID3 : 1;
unsigned : 1;
unsigned UOWN : 1;
};
struct {
unsigned : 2;
unsigned PID : 4;
unsigned : 2;
};
} STATUS;
void PrintIt() {
printf("Size of UNION is %d \n", sizeof(STATUS));
}
Run Code Online (Sandbox Code Playgroud)
它应该是所有成员中最大的,每个成员只有8位。
引起我注意并促使我对此进行调查的代码是:
STAT.BC9 = 0;
STAT.BC8 = 0;
STAT.Val |= byteToSend;
Run Code Online (Sandbox Code Playgroud)
第三行合并到第一行和第二行的值中。
所以我想测试一下,结果是 4 个字节,而不是 1 个字节。我什至在几个不同的编译器中测试了它(因此 MS Visual C 使用#pragma)。
每个成员都是 8 位,最后两个结构重叠,将 PID 值放置在同一内存位置。然而,无论我使用编译器来评估它,这都是 4 个字节。
向联合添加结构的行为是否存在某些问题?
任何解释表示赞赏。
虽然 C 标准中没有明确指定,但位域通常会占用与其声明的基类型相对应的单元。
在这种情况下,所有位域都被声明为unsigned. 该类型在您的系统上可能为 4 个字节,因此位域占用该类型的一个单元。
如果将字段的类型更改为unsigned charor ,uint8_t它们应该只占用一个字节。请注意,这假设您的编译器允许将这些类型用于位域,尽管大多数编译器都这样做。
C有隐式类型的概念。因此unsigned将声明一个unsigned int. 但事情变得更奇怪了。const如果您只使用or static/ ,情况也是如此auto。
const x = 5; // Declares a const int variable
static x; // Declares a static int variable
const static unsigned x = 5; // Declares a const static unsigned int variable
Run Code Online (Sandbox Code Playgroud)
你想要的是一个unsigned char.
它应该是所有成员中最大的,每个成员只有8位。
它至少应该是这个尺寸。没有什么可以阻止它变得更大。