不管官方或其他人怎么说,这都不是未定义的行为,因为它是由标准定义的。p->s
,除了用作左值时,其结果等于的指针(char *)p + offsetof(struct T, s)
。特别是,这是char
malloc对象内部的有效指针,紧随其后的有100个(或更多,取决于对齐方式)连续地址,这些地址也可用作char
已分配对象内部的对象。该指针是通过使用得到的事实->
,而不是明确地将偏移到返回的指针malloc
,转换为char *
,是无关紧要的。
从技术上讲,它p->s[0]
是char
结构中数组的单个元素,接下来的几个元素(例如p->s[1]
至p->s[3]
)很可能在结构中填充字节,如果您对整个结构执行赋值,则可能会损坏这些字节,但如果仅访问单个结构,则不会损坏成员,其余元素是分配的对象中的附加空间,您可以随意使用,只要您遵守对齐要求(并且char
没有对齐要求)即可。
如果担心结构中与填充字节重叠的可能性可能会以某种方式调用鼻恶魔,则可以通过将1
in 替换为[1]
确保结构末尾没有填充的值来避免这种情况。一种简单但浪费的方法是使用除了最后没有数组之外的相同成员来构造结构,并将其s[sizeof struct that_other_struct];
用于该数组。然后,p->s[i]
在for中明确定义为struct中数组的元素,并在struct i<sizeof struct that_other_struct
末尾的地址处将其定义为char对象i>=sizeof struct that_other_struct
。
编辑:实际上,在上述获取正确大小的技巧中,您可能还需要在数组之前放置一个包含每个简单类型的并集,以确保数组本身以最大对齐方式开始,而不是在其他元素的填充中间。再说一次,我不认为这是必要的,但是我将其提供给最偏执的语言律师。
编辑2:由于标准的另一部分,填充字节的重叠绝对不是问题。C要求,如果两个结构在其元素的初始子序列中一致,则可以通过指向任一类型的指针来访问公共的初始元素。因此,如果相同的结构struct T
,但具有较大的阵列天线的最终被宣布,该元件s[0]
将不得不与元件重合s[0]
在struct T
,并且这些附加的元件的存在不能影响或通过访问较大结构的共同要素的影响使用指向的指针struct T
。