【发布时间】:2016-07-28 16:59:53
【问题描述】:
好的,所以我正在阅读标准论文 (ISO C11) 中解释灵活数组成员的部分(在 6.7.2.1 p18)。它是这样说的:
作为一种特殊情况,结构的最后一个元素具有多个 命名成员可能具有不完整的数组类型;这被称为 灵活的数组成员。在大多数情况下,灵活的数组成员 被忽略。特别是,结构的大小就像 灵活的数组成员被省略了,除了它可能有更多 比遗漏所暗示的尾随填充。但是,当
.(或->) 运算符的左操作数是(指向)具有灵活数组成员的结构,右操作数命名该成员, 它的行为就好像该成员被替换为最长的数组 (具有相同的元素类型)不会使结构变大 比被访问的对象;数组的偏移量应保持 灵活数组成员的那个,即使这与那个不同 的替换阵列。如果这个数组没有元素,它 表现得好像它只有一个元素,但如果有的话,行为是未定义的 尝试访问该元素或生成指针 one 过去了。
下面是一些示例(p20):
示例 2 声明后:
结构 struct s 有一个灵活的数组成员 d。一种典型的方式 使用这个是:struct s { int n; double d[]; };并假设对 malloc 的调用成功,则指向的对象 在大多数情况下,by p 的行为就像 p 已被声明为:int m = /* some value */;
struct s *p = malloc(sizeof (struct s) + sizeof (double [m]));(在某些情况下,这种等价性被打破;在 特别是成员 d 的偏移量可能不同)。struct { int n; double d[m]; } *p;
标准中添加的剧透示例不是文档。
现在是我的例子(从标准扩展):
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
struct s { int n; double d[]; };
int m = 7;
struct s *p = malloc(sizeof (struct s) + sizeof (double [m])); //create our object
printf("%zu", sizeof(p->d)); //retrieve the size of the flexible array member
free(p); //free out object
}
在线example.
现在编译器抱怨 p->d 的类型不完整 double[] 根据标准文件显然不是这种情况。这是 GCC 编译器的错误吗?
【问题讨论】:
-
这很有趣,但我没有看到编译器真正知道这个大小的干净方法。
-
@EugeneSh。好吧,根据标准,它似乎应该这样做。
-
标准明确规定
sizeof运算符的操作数必须是完整类型的对象。 -
@CisNOTthatGOODbutISOisTHATBAD;它在哪里说它有完整的类型?
-
@hacks 它的行为就像该成员被替换为最长的数组(具有相同的元素类型),不会使结构大于被访问的对象 - 它可以理解为表现为一个完整的类型。
标签: c arrays language-lawyer sizeof c11