为什么GCC只允许零长度数组作为最后一个成员?

时间:2015-12-17 10:25:59

标签: arrays gcc

根据这个,

https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html

据说好处是

  

它们作为结构的最后一个元素非常有用   可变长度对象的标题

这是什么意思?

3 个答案:

答案 0 :(得分:3)

零长度数组是一个GCC扩展名(读作:非标准),你不应该使用它。

虽然C的最新版本允许类似(具有空括号的灵活数组成员),但C ++不知道这样的事情。由于人们经常混合使用C和C ++,这可能会引起混淆。

相反,应该使用长度为1的数组,这在C和C ++下都符合标准,并且只适用于每个编译器

这对什么有用?

有时您需要访问"无效"越界数据知道它在现实中是有效的。从严格意义上讲,这是未定义的行为(因为您正在访问不确定的越界值,并且使用不确定的值是UB),但这只是编译器知道的,而不是它的事实,所以它然而,#34;工作正常"。

例如,您可能会在网络上接收由标记字,长度和与给定长度相对应的数据量组成的成帧数据。或者操作系统函数可能会向您返回可变数量的结果(例如,一些Win32 API函数以这种方式工作)。
在任何一种情况下,您在此结构的末尾都有一个未知的(编译时未知)元素数量,因此无法定义一个合法的结构来保存所有内容。
这就是灵活阵列成员的用途。有了它,它解释了为什么它们也必须是最后一个成员。对于任何可能具有任何尺寸的东西都没有意义。在任何地方,但最后 - 编译器不可能在其后面布置任何成员,而不知道它的大小。

(如果您想知道编译器如何释放存储而不知道对象的大小... 它不能!通常存在一个显式函数来释放这样的对象API的一部分,负责处理这个确切的问题。)

答案 1 :(得分:1)

最好用一个小例子进行演示:

#include <stdio.h>
#include <stdlib.h>


#define BLOB_TYPE_FOO  0xBEEF


struct blob {
    /* Part of your object header... perhaps describing the type of blob. */
    int type;

    /* This is actually the length of the "data" field below */
    unsigned length;

    /* The data */
    unsigned char data[];
};


struct blob *
create_blob(int type, size_t size)
{
    /* Allocate enough space for the "header" and "size" bytes of data. */
    struct blob *x = calloc(1, sizeof(struct blob) + size);
    x->type = type;
    x->length = size;

    return x;
}


int
main(void)
{
    /* Note that sizeof(struct blob) doesn't include the data field. */
    printf("sizeof(struct blob): %zu\n", sizeof(struct blob));

    struct blob *x = create_blob(BLOB_TYPE_FOO, 1000);

    /*
        You can manipulate data here, but be careful not to exceed the
        allocated size.
    */

    size_t i;

    for (i = 0; i < 1000; i++)
    {
        x->data[i] = 'A' + (i % 26);
    }

    /*
        Since data was allocated with the rest of the header, everything is
        freed.
    */
    free(x);

    return 0;
}

关于此设置的好处是sizeof(struct blob)表示&#34;对象标题的大小&#34; (在我的机器上,那是8个字节),并且由于你将整个对象分配在一起,所以只需要一个free()来释放内存。

正如其他人在此处所述,这是一个非标准的扩展,您应该考虑小心使用它。 Damon的答案是更好的方法,尽管sizeof()操作的大小不是很合适(它有点太大而无法表示实际标题的大小)。但是,解决这个问题并不难。

答案 2 :(得分:0)

你不能拥有0长度的数组,因为如果你试图制作一个零长度数组,那么这意味着你要创建一个指向 nothing 的指针not correct。 C标准说:

  
      
  • 灵活数组成员写为内容[],不带0。
  •   
  • 灵活数组成员的类型不完整,因此可能无法应用sizeof运算符。作为零长度数组原始实现的一个怪癖,sizeof的计算结果为零。
  •   
  • 灵活数组成员可能只显示为非空的结构的最后一个成员。
  •   
  • 包含柔性阵列成员的结构或包含这种结构的联合(可能是递归地),可以不是结构的成员或阵列的元素。 (但是,GCC允许这些用途作为扩展。
  •