很明显C cannot insert padding between their elements中的数组。但是,有没有规则说他们不能在整个数组的 end 添加尾随填充?
即。该计划是否保证在各地都能得到相同的结果?
#include <stdio.h>
int main(void) {
typedef char a[3];
typedef a b[3];
printf("%zu %zu\n", sizeof(a), sizeof(b)); // -> 3 9
}
据我所知,在a
的大小中添加一个或大小为5的尾随字节(可能是误导的优化尝试)不会破坏数组访问规则(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
的数组元素的数量,无论如何这可能适用于所有地方 - 有没有已知的情况不是吗?
答案 0 :(得分:6)
我认为标准实际上从来没有必要说明数组没有填充,原因很简单,因为没有理由认为这种填充对任何实现都有用。
那就是说,我相信标准禁止这样的填充,通过==
运算符的描述。
6.5.9平等运营商
<强>语义强>
6当且仅当[...]或1是指针时,两个指针才相等 到一个数组对象的末尾,另一个是指向不同数组对象的开头的指针,该对象碰巧紧跟在地址空间中的第一个数组对象之后。
鉴于
int array[2][2];
表达式&array[0][2]
点是指向第一个数组子对象末尾的指针。 &array[1][0]
是指向第二个数组子对象的指针,它紧跟在内存中的第一个数组之后。这些指针需要比较相等。如果int[2]
有尾随填充,如果sizeof(int[2]) > 2 * sizeof(int)
,我无法想象任何实现如何使两个指针比较相等。