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

Eri*_*hil 27 c arrays size language-lawyer

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实现需要对大型数组进行额外的内存管理,因此创建一个数组需要创建一些额外的数据来帮助管理内存.)

ex *_*ilo 20

是的,则要求的阵列的大小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.由于标准中没有提到这些可能性,因此可以合理地得出结论:数组首先不得有尾随填充.

  • @Joshua - 不确定我是否在这里关注你 可以将任意量的填充添加到这些结构中的任何一个. (2认同)
  • @Joshua - 的确,但我总是很想在黑暗的小巷里遇见[DeathStation 9000](http://www.statemaster.com/encyclopedia/DeathStation-9000). (2认同)

R..*_*R.. 8

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

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

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

需要注意的是它并没有说像"连续分配的非空集的对象和填充",所以数组刚刚的对象.因此,似乎没有理由认为sizeof数组[类型]可以产生除连续对象集合的大小之外的任何结果,这显然N是单个元素类型的大小.

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