Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 零长度数组与指针_C_Arrays_Pointers - Fatal编程技术网

C 零长度数组与指针

C 零长度数组与指针,c,arrays,pointers,C,Arrays,Pointers,编辑:很明显,这在各种C标准中是不允许的/已经改变了。为了我自己假设的好处,让我们假设我们使用的是没有标准或警告选项的gcc test.c 我特别关注的是引擎盖下的细节。我已经补充了我目前的理解。我说得对吗 char **c1; //Size for a pointer is allocated on the stack. sizeof(c1) == sizeof(void*) char *c2[0]; //Nothing is allocated on the stack. sizeof

编辑:很明显,这在各种C标准中是不允许的/已经改变了。为了我自己假设的好处,让我们假设我们使用的是没有标准或警告选项的
gcc test.c

我特别关注的是引擎盖下的细节。我已经补充了我目前的理解。我说得对吗

char **c1;   //Size for a pointer is allocated on the stack. sizeof(c1) == sizeof(void*)
char *c2[0]; //Nothing is allocated on the stack.  sizeof(c2) == 0
除了sizeof之外,我不知道这两个案例之间还有什么不同之处吗

据我所知,这通常用于结构末尾的可变长度数组。但是呢

struct b {
   char *c[0] //sizeof(b) is 0?  where does c point?
};

int j;
struct b myb; //myb.c == (&j)+1 == $esp?

此外,如果指针的空间从未分配到任何地方,那么零长度数组的地址是如何知道的?我想知道一个常规数组的地址的方法也是一样的,但我现在很难把注意力集中在它上面。

ISO C禁止
0
长度的数组

char **c1;
这定义了指向字符指针的指针类型的对象
c1

char *c2[0];
这是一个编译错误。不允许。不是C,不是C++。< /P>
struct a {
  int i;
  char c[0]; //sizeof(a) is sizeof(int)?  a.c == (&i)+1?
};
错误,如前所述--数组的大小必须大于零

 struct a {
  int i;
  char c[1]; 
};
也被称为结构黑客。在几乎所有操作系统(Linux、Windows)上的低级代码中被滥用

C99确实为我们提供了一个规模较小的阵列,称为灵活阵列成员:

struct a {
  int i;
  char c[]; /* note: no size */ 
};

我唯一一次看到实际使用的零长度数组是当您想要一个可变长度的结构时

在这个例子中,我们从

您不希望在上述结构中使用指针,因为您希望内容成为该结构分配内存的一部分

如果在上面的结构上执行sizeof,那么它不包含任何内容空间。我不确定这是否成为标准,它会在各种编译器上发出警告。

来自C99标准(7.20.3),处理分配函数:

每个这样的分配应产生一个指向与任何其他对象不相交的对象的指针

[……]

如果请求的空间大小为零,则行为由实现定义: 要么返回空指针,要么行为就好像大小为 非零值,但返回的指针不得用于访问对象


换句话说,在没有初始值设定项的堆栈上声明
b
(其中
b
is将
c
声明为
c[]
而不是
c[0]
)的情况下,
b
实际使用的空间的实际大小将大于0,因为您无法访问
b
的任何部分。如果它是通过
malloc
分配的,则它将作为
0
返回,或者作为无法访问的某个唯一值返回(如果您使用
sizeof(b)
)。

您可以从。但这主要集中在将零长度数组作为结构的最后成员这一主题上。它没有给出关于sizeof的直接答案


(正如其他人已经明确指出的,零长度数组不在标准C中,但它们在GNU C中。)

一个数组不能有零大小

ISO 9899:2011 6.7.6.2:

If the expression is a constant expression, it shall have a value greater than zero.
上述文本适用于普通数组(§1)和VLA(§5)。这是C标准中的规范性文本。编译器不允许以不同的方式实现它


gcc-std=c99-pedantic对此给出警告。

Ahh,但如果您重新键入它,则为ias char c[];如果c是a的最后一个成员,那么从C99起它将是合法的。哇!考虑到gcc将编译它,我所有的评估都正确吗(关于地址和谁指向哪里)?@litb:我不同意这个理由,因为根据我的理解,编译器可以自由地假设,如果数组的声明大小为1,那么对数组的任何访问都会访问第一个元素(任何其他访问都是未定义的行为,即使在结构的末尾有分配的空间)。对于零大小的数组有一个特例(声明编译器不得对“真实”大小进行假设)似乎比要求程序员使用不符合标准的黑客或猜测最大大小更简洁。我认为这个答案有点迂腐。OP似乎在试图理解为什么使用某个习语。根据C99,该习语是否合法是一个很好的细节,可以添加到完整的解释中。但事实是有些复杂的代码(例如Git)利用它,人们想了解代码在做什么。@EricWalker同意。零长度数组在GNU C中完全有效,所以这个答案感觉不完整。我在Linux内核的Wi-Fi驱动程序代码中看到过这种用法。另外,请看标准的这一部分是否只适用于malloc?我看不出前面的相关内容答案的一部分。“实际使用的空格将大于0,因为您无法访问b的任何部分”感谢您解释此成语的实际用法。如果您试图理解使用空格的代码,那么这样做是否正确并不重要。另请参阅。
    struct line {
       int length;
       char contents[0];
     };

     struct line *thisline = (struct line *)
       malloc (sizeof (struct line) + this_length);
     thisline->length = this_length;
ISO 9899:2011 6.7.6.2:

If the expression is a constant expression, it shall have a value greater than zero.