我有以下类型定义:
typedef union{
unsigned int Entry;
struct {
unsigned char EntryType;
unsigned char EntryOffset[3];
};
} TLineDescriptor;
我也有类型的以下用法:
TLineDescriptor LineDescriptor;
LineDescriptor.Entry = 40;
LineDescriptor.EntryType = 0x81;
sizeof(LineDescriptor)
表明这个变量占用了4个字节的内存,起初我假设它保存了int或结构。
cout << LineDescriptor.Entry << " " << LineDescriptor.EntryType << endl;
但是,上面的行打印了两个不同的值,即129 ü
,LineDescriptor.Entry
显然是指保存值0x81的内存位置。我不确定40岁时发生了什么。
但很明显,我的假设是错误的。有人可以正确解释和解释类型定义吗?理解它对于我使用我发现的代码至关重要。
提前谢谢。
答案 0 :(得分:1)
以这种方式打印EntryType:
cout << "0x" << hex << (unsigned)LineDescriptor.EntryType << endl;
你会看到ü是0x81。
打印此内容:
cout << LineDescriptor.Entry
是未定义的行为 - 因为联合中只有一个元素可以在某个时刻处于“活动状态” - 而您的最后一个分配是EntryType。
然而,假设我们可以假设这实际上并不像C ++希望的那样未定义,那么129来自:
Entry=40
- 在您的系统28 00 00 00
上采用二进制格式(首先是不太重要的字节)。
使用LineDescriptor.EntryType = 0x81;
您更改了第一个字节:81 00 00 00
- 因此您输入的条目现在为129.
进行此实验并获得其他结果:
TLineDescriptor LineDescriptor;
LineDescriptor.Entry = 256;
LineDescriptor.EntryType = 0x81;
cout << LineDescriptor.Entry << " " << unsigned(LineDescriptor.EntryType)
<< endl;
>> 385 129
答案 1 :(得分:1)
实际上,这些不是不同的值。 129
是字符ü
的字符代码。 operator <<
ostream
对int
和char
数据类型的处理方式不同,打印第一个的数值和后一个的字符值。
因此,您对联合类型的理解是正确的。但请注意,在处理联合类型时,字节序可能是一个问题。例如,在little-endian机器上EntryType
将保留Entry
的最低有效字节和其他EntryOffset
数组。但是在大端机器上,EntryType
将保留最重要的字节。
答案 2 :(得分:1)
你的假设没有错,联盟将持有 int或struct。当您将值0x81
分配给EntryType字段时,您之前分配给Entry
的整数将被覆盖,这就是为什么当您cout
这两个字段时,您获得的数量相同两者,一个作为int(129),一个作为char(ü)。两者都具有十六进制值0x81
。
答案 3 :(得分:1)
它在相同时保留int
和struct
,并且两者占用相同的内存空间。通过访问TLineDescriptor::Entry
,您可以将这4个字节解释为int
。如果您通过struct
访问它,则会将其解释为4 unsigned char
s。
LineDescriptor.Entry = 40;
这将4个字节设置为int
值40.在小端系统中,这意味着第一个字节为40,其他3个字节为0.
LineDescriptor.EntryType = 0x81;
这将第一个字节设置为值129(0x81)。 (在小端系统中,这意味着Entry
的值现在也是129,只要你将其余部分设置为0)。
关于不同的输出:当您输出EntryType时,它将显示为字符而不是数字。尝试:
cout << LineDescriptor.Entry << " " << static_cast<int>(LineDescriptor.EntryType) << endl;