很明显,C中的数组不能在它们的元素之间插入填充.但是,有没有规则说他们不能在整个数组的末尾添加尾随填充?
即这个计划是否保证在各地都能得到相同的结果?
#include <stdio.h>
int main(void) {
typedef char a[3];
typedef a b[3];
printf("%zu %zu\n", sizeof(a), sizeof(b)); // -> 3 9
}
Run Code Online (Sandbox Code Playgroud)
据我所知a,在一个误导的优化尝试中添加一个或五个大小的尾随字节,不会破坏数组访问规则(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);
Run Code Online (Sandbox Code Playgroud)
(好的,所以OpenGL可以接受步幅值,所以这是一个不好的例子,但你明白了)
就此而言,我从广泛的概念(甚至标准中的例子)中假设你可以得到数组的元素数量,sizeof无论如何这可能在任何地方都适用 - 有没有任何已知的情况,它不是"T?
小智 6
我相信标准实际上并没有必要说明数组没有填充,原因很简单,因为没有理由说这种填充可能对任何实现都有用.
也就是说,我确实相信标准禁止这样的填充,通过==操作员的描述.
6.5.9平等运营商
语义
6两个指针比较相等,当且仅当[...]或者一个是指向一个数组对象末尾的指针而另一个指针指向另一个数组对象的开始时,该指针恰好跟随第一个数组地址空间中的对象.
特定
int array[2][2];
Run Code Online (Sandbox Code Playgroud)
表达式&array[0][2]点是指向第一个数组子对象末尾的指针.&array[1][0]是指向第二个数组子对象的指针,它紧跟在内存中的第一个数组之后.这些指针需要比较相等.如果int[2]有尾随填充,如果sizeof(int[2]) > 2 * sizeof(int),我无法想象任何实现如何使两个指针比较相等.