考虑以下联合:
typedef union {
struct { // Anonymous struct
int red;
int green;
int blue;
};
int colorChannels[3];
} Color;
无论系统编译或执行此代码的系统如何,匿名结构中的字段是否总是与colorChannels中的索引对齐?
换句话说,规范是否需要内存地址 myColor.colorChannels[0]
与地址相同 myColor.red
?
另外,如果代码编译为C ++而不是C,答案会有所不同吗?
请注意,我问的是联合中每个元素具有相同类型/大小的具体情况(即 int
在这种情况下)
无论系统编译或执行此代码的系统如何,匿名结构中的字段是否总是与colorChannels中的索引对齐?
不必要。该实现可以在单个变量之间添加字节“填充” struct
。 “填充”只是在变量之间或之后插入到内存定义中的额外字节的内存 struct
以实现定义的方式。如果发生这种情况,那么整数数组将不会与内存布局对齐 struct
(除非填充仅在结尾处 struct
, 也许)。变量的顺序 struct
在内存中应该跨实现保持一致(在该变量中) a
接下来是 b
其次是 c
在内存中),但是,再次,之间的字节填充仍然可以存在(例如, a
接下来是 b
在内存中,但之间有填充 a
和 b
这样他们就不会在记忆中彼此相继)。
对于像gcc这样的编译器, 有办法修改它如何处理填充。这可以帮助保证 struct
将与您的整数数组在内存中对齐,但这可能会导致下游的其他内存问题。
换句话说,规范是否要求myColor.colorChannels [0]的内存地址与myColor.red的地址相同?
如果之间没有填充 red
, green
,和 blue
的 struct
,那么索引 colorChannels
将与内存中的每个变量匹配。
C标准对此没有任何保证,但它可能对任何存在的实际系统都是正确的。
我建议在代码中添加一个编译时检查,这样如果有一些系统添加了填充,你会得到一个编译错误,你可以在那时处理:
_Static_assert( sizeof(Color) == 3 * sizeof(int), "We're on a weird system boys." );
NB。 _Static_assert
在C11中添加,在此之前你可以使用一些黑客 如此处所述