结构中的Unsized数组声明

时间:2013-11-26 15:19:04

标签: c arrays flexible-array-member

为什么 C 允许这样做:

typedef struct s
{
  int arr[];
} s;

数组arr没有指定大小?

2 个答案:

答案 0 :(得分:12)

这是C99功能称为灵活数组,主要功能是允许use variable length array like features inside a struct R .. 在此answer to another question on flexible array members中提供一个通过指针使用灵活数组的好处列表。 6.7.2.1 结构和联合说明符 16 中的draft C99 standard表示:

  

作为一种特殊情况,具有多个命名成员的结构的最后一个元素可以   有一个不完整的数组类型;这被称为灵活的阵列成员。在大多数情况下,   灵活的数组成员被忽略。特别是,结构的大小就像是   省略了灵活的数组成员,除了它可能有更多的尾随填充   遗漏意味着。 [...]

因此,除了 struct 所需的空间之外,如果你有一个s*,你将为数组分配空间,通常你会在结构中有其他成员:

s *s1 = malloc( sizeof(struct s) + n*sizeof(int) ) ;

标准草案实际上在段落 17 中有一个有启发性的例子:

  

示例声明后:

  struct s { int n; double d[]; };
     

结构struct s具有灵活的数组成员d。一种典型的使用方式       是:

   int m = /* some value */;
   struct s *p = malloc(sizeof (struct s) + sizeof (double [m]));
     

并假设对malloc的调用成功,p指向的对象       在大多数情况下,表现为p被声明为:

    struct { int n; double d[m]; } *p;
     

(在某种情况下,这种等同性被打破;特别是,        成员d的偏移可能不一样。)

答案 1 :(得分:4)

您可能正在寻找C99中的灵活阵列。 灵活数组成员是struct / union末尾未知大小的成员。

  

作为一种特殊情况,结构的最后一个元素有多个   命名成员可能具有不完整的数组类型;这叫做a   灵活的阵列成员。在大多数情况下,灵活的阵列成员   被忽略了。特别是,结构的大小就像是   柔性阵列成员被省略,除了它可能有更多   尾随填充比遗漏意味着暗示。

您也可以首先查看reason for the struct hack

  

目前尚不清楚它是合法还是便携,但它相当受欢迎。该技术的实现可能如下所示:

    #include <stdlib.h>
    #include <string.h>

    struct name *makename(char *newname)
    {
        struct name *ret =
            malloc(sizeof(struct name)-1 + strlen(newname)+1);
                    /* -1 for initial [1]; +1 for \0 */
        if(ret != NULL) {
            ret->namelen = strlen(newname);
            strcpy(ret->namestr, newname);
        }

        return ret;
    }
  

此函数使用。分配名称结构的实例   调整大小,以便namestr字段可以保存请求的名称   (不只是一个字符,如结构声明所暗示的那样)。

     

尽管它很受欢迎,但该技术也有点臭名昭着 -   丹尼斯·里奇(Dennis Ritchie)将其称为“C实施中无根据的愚蠢行为。”官方解释认为它不是   严格符合C标准,虽然它似乎确实有效   在所有已知的实现中。检查数组边界的编译器   小心翼翼地发出警告。