C标准是否要求n个元素数组的大小是元素大小的n倍?

C标准是否要求n个元素数组的大小是元素大小的n倍,可以通过显式语句还是通过严格的逻辑推理来满足其要求?

例如, int (*x)[5] = malloc(5 * sizeof **x); 无法为五个int的数组请求足够的空间?

C 2011 [N1570] 6.5.3.4 7显示了将数组中的元素数量计算为sizeof array / sizeof array[0] 。 但是,例子不是标准的规范部分(根据前言第8段)。

6.2.5 20表示数组类型描述了具有特定类型的连续分配的非空对象集,但对所需的总内存没有提及。

这只是一个语言律师问题; 实际的实现是无关紧要的。 (为了安抚那些想要具体示例的人,假设一个C实现需要对大型数组进行额外的内存管理,因此创建一个数组需要创建一些额外的数据来帮助管理内存。)

描述数组表示的唯一文本非常简洁,并且在6.2.5¶20中找到了:

可以从对象和函数类型构造任意数量的派生类型,如下所示:

  • 数组类型描述了具有特定成员对象类型的连续分配的非空对象集,称为元素类型。 只要指定了数组类型,元素类型就应该是完整的。 数组类型的特征在于它们的元素类型和数组中元素的数量。 数组类型据说是从其元素类型派生的,如果它的元素类型是T,则数组类型有时称为”T’数组。 从元素类型构造数组类型称为“数组类型派生”。

请注意,它没有说“连续分配非空对象和填充集”,因此数组只是对象。 因此,似乎没有理由认为数组[类型]的大小可以产生除连续对象集合的大小之外的任何结果,这显然是单个元素类型大小的N倍。

值得注意的是,填充不是可以单独存在的东西,因为它没有指定不存在。 C指定类型的表示(6.2.6)并明确指定在适当时填充位和字节的可能性。 没有关于数组填充的文本,因此它不是它们表示的一部分。

是的,要求数组T[n]的大小为n * sizeof (T)

标准定义了§6.2.5/ 20中的数组:

数组类型描述了具有特定成员对象类型的连续分配的非空对象集。

此外, sizeof运算符产生数组中的总字节数(第6.5.3.4 / 4节 ):

sizeof应用于具有数组类型的操作数时,结果是数组中的总字节数。 当应用于具有结构或联合类型的操作数时,结果是此类对象中的总字节数,包括内部和尾部填充。

由于数组由连续的对象分配组成,因此不能有内部填充。 并且由于仅在联合和结构的上下文中关于sizeof运算符明确提及尾随填充,因此很明显数组预期不具有这样的尾随填充。

最后,请注意在§6.2.6.1/ 4中说明:

存储在任何其他对象类型的非位字段对象中的值由n x个CHAR_BIT位组成,其中n是该类型对象的大小(以字节为单位)。 可以将该值复制到unsigned char [ n ]类型的对象中(例如,通过memcpy); 生成的字节集称为值的对象表示

假设数组可以有尾随填充字节,考虑一个数组unsigned char A[n] ,并进一步考虑数组unsigned char B[sizeof A]A[]所有字节(包括可能的填充字节)都是复制。 现在, A[] 必须B[]大小相同,因为( §6.2.6.1/ 8 ):

如果将运算符应用于具有多个对象表示的值,则使用哪个对象表示不应影响结果的值。

这意味着B[] 必须没有尾随填充,这意味着数组可以有尾随填充字节,除非在标准中没有提到的某些特殊条件下,或者除了unsigned char数组之外,数组可能有尾随填充。 由于标准中没有提到这些可能性,因此可以合理地得出结论:数组首先不得有尾随填充。