数组可以有尾随填充吗?

很明显,C中的数组不能在它们的元素之间插入填充 。 但是,是否有任何规则说他们不能在整个数组的末尾添加尾随填充?

即,这个计划保证在各地给出相同的结果吗?

#include  int main(void) { typedef char a[3]; typedef ab[3]; printf("%zu %zu\n", sizeof(a), sizeof(b)); // -> 3 9 } 

据我所知,在一个误导的优化尝试中添加一个或五个大小的尾随字节,可能不会破坏数组访问规则( b[1][1]仍然完全映射到*(&b + sizeof(a) * 1 + 1)无论其包含a对象的大小如何,并且访问超出包含的a的长度仍然是UB)。

我在C标准中找不到任何地方,它实际上直接说数组的大小是元素类型的大小乘以元素的数量。 6.5.3.4只说sizeof返回数组中的“字节数”(它确实给出了sizeof array / sizeof array[0]作为代码示例,但它只是一个例子 – 它并没有说它必须工作 ,它没有提供任何细节)。

隐式保证对于编写依赖于精确数据布局的可移植代码非常有用,例如传递打包的RGB值:

 typedef uint8_t RGB[3]; RGB * data = ...; glColorPointer(3, GL_UNSIGNED_BYTE, 0, data); 

(好的,所以OpenGL可以接受步幅值,所以这是一个不好的例子,但你明白了)

就此而言,我从广泛的概念(甚至是标准中的例子)中假设你可以得到带有sizeof的数组元素的数量,这可能在任何地方都适用 – 有任何已知的情况吗?是不是?

我相信标准实际上并没有必要说明数组没有填充,原因很简单,因为绝对没有理由说这种填充可能对任何实现都有用。

也就是说,我相信标准禁止这样的填充,通过==运算符的描述。

6.5.9平等运营商

语义

6两个指针比较相等,当且仅当[…]或者一个是指向一个数组对象末尾的指针而另一个指针指向另一个数组对象的开始时,该指针恰好跟随第一个数组地址空间中的对象。

特定

 int array[2][2]; 

表达式&array[0][2] points是一个超过第一个数组子对象末尾的指针。 &array[1][0]是指向第二个数组子对象的指针,它紧跟在内存中的第一个数组之后。 这些指针需要比较相等。 如果int[2]有尾随填充,如果sizeof(int[2]) > 2 * sizeof(int) ,我无法想象任何实现如何使两个指针比较相等。