来自C11标准
我刚刚阅读了C11标准中的内容,无法理解为什么存储在结构/联合对象中的值,填充字节的对象表示采用未指定的值?
我知道标准没有规定任何要求的具体方法。
当值存储在结构或联合类型的对象(包括成员对象)中时,与任何填充字节对应的对象表示的字节将接受未指定的值。 结构或联合对象的值绝不是陷阱表示,即使结构或联合对象的成员的值可能是陷阱表示。
有人能给我举个例子来更好地理解这句话吗?
发布于 2017-11-10 14:46:21
基本上是这样的:
因此:您不能信任填充字节具有任何给定的值(除了它们不能是陷阱表示)。填充字节的值可能因情况不同而不同--不能保证它们的值是一致的。
考虑一个没有陷阱表示的普通32位二位补码系统:
typedef struct
{
uint8_t u8;
uint32_t u32;
} something_t;
something_t thing1 = {1, 2};
something_t thing2 = {3, 4}在这里,一个可能的内存布局是这样的(十六进制,小endian):
01 AA BB CC 02 00 00 00 // thing 1
03 55 66 77 04 00 00 00 // thing 2
^ ^ ^
u8 padding u32在thing1中,01是u8成员,AA BB CC序列是填充字节的未指定值,02 00 00 00是u32成员。
如果我们现在编写thing1 = thing2,编译器可以执行以下操作之一:
thing2并覆盖所有thing1,包括填充,如果这是最有效的,u8和u32,但不要写入填充字节,使它们保持原样,从而导致thing1现在具有内存布局03 AA BB CC 04 00 00 00。这就是为什么我们不能将结构与==运算符或像memcmp()这样的函数进行比较的原因。
发布于 2017-11-10 12:38:51
假设sizeof(long)=8,sizeof(int)=4,64位机器:
struct {
int a;
long b;
} obj = {0, 0};在&obj.a和&obj.b之间有4个字节的填充是有意义的。填充物的内容应该是什么?为什么强迫运行时在那里放置任何东西?obj的布局也可以是0x00000000, 0xDEADBEEF, 0x00000000, 0x00000000 --即4字节的垃圾,因为不需要访问它们(因此不应该访问它们)。
通常情况下,问题是相反的--如果您认为应该指定它(也就是说,您希望迫使编译器编写人员做更多的工作,以及可能效率较低的工作),那么应该由您来解释原因。
发布于 2017-11-10 12:34:50
问题是,你永远不知道结构或结合的元素在记忆中是如何事先被确定的。所述填充位可因系统而异。
此外,还可以考虑编译器对此的处理方法。所实现的布局优化是不同的。在某些编译器中,它将是一个,然后在另一个编译器中有所不同。
陷阱表示是适合于类型占用空间的位模式,但如果用作该类型的值,则会触发未定义的行为。
例如:-
struct a{
int a;
char b;
};在这里,结构的大小不一定是a和b的大小。填充正在添加,这是标准的事情,不评论。您希望将结构作为一个整体来处理,表示可以工作。但是,如果要以严格的8字节表示形式访问元素,则可能会失败。
https://stackoverflow.com/questions/47222888
复制相似问题