有人说C语言是一个很诡异的语言,所以有时候我们会见到一些比较奇怪的定义,比如:
struct A{
int a;
int data[]
};
这个看起来确实很奇怪,为什么数组没有定义大小呢?
但实际上这段代码不仅可以通过大部分编译器,并且用途还很广泛。我工作的时候就遇到了不少这样的代码,并且还是比较关键的代码。
不过实际上事情并没有那么复杂和难以理解,不用看那些复杂的关于零长度数组是否符合C标准,以及不完整类型等等没见过的名词,其实道理很简单,C也不会专门为了这个而搞出来很复杂的规则。
让我们来看看,什么地方还会用到这样类似的东东:
int f(int array[])
{
...
}
int main(void)
{
int a[10];
...
f(a);
...
}
想想看,是不是一样的道理?
int a[]无论怎么用,都是一个意思,就是说明a是一个数组,但是不知道它的大小。
当然在struct A的定义中,与这里还是有些不同的,因为int data[]并没有占用实际的空间,sizeof(struct A) = 2(或者是4,依赖于平台)。
另外,int data[0]在有些编译器上也可以通过,并且和int data[]具有相同的效果,所以上面的结构体声明可能看起来象下面这样:
struct A{
int a1;
int data[0];
};
这种写法不推荐使用,因为不符合C的标准,而且看起来更怪更难以理解。
引用别人的一个例子,就可以更深入的理解了:
#include "stdio.h"
#include "stdlib.h"
struct A{
short a1;
short next[0];
} * pA = NULL;
struct B{
short a1;
short next[1];
};
main()
{
short abc[10];
int i;
printf("sizeof(struct A)=%d, sizeof(short)=%d, sizeof(struct B)=%d/r/n", sizeof(struct A), sizeof(short), sizeof(struct B));
for (i=0; i<10; i++) abc[i] = i;
pA = (struct A * ) abc;
for (i=0; i<10; i++) {
printf("i: %d, i.next:%d/r/n", pA->a1, pA->next[0]);
pA++;
/*
注意与的不同,下面的语句要考虑到入栈的顺序,i和i.next的输出是相同的
printf("i: %d, i.next:%d/r/n", pA->a1, pA++->next[0]);
*/
};
getch();
}
注:例子来源于http://www.etcell.com/soft/topicView.aspx?Id=38200,我是用baidu的cache看到的,看不到作者的名字,就不写了,大家看到了帮忙告诉我,我写上。另外,代码修改了一句,以便突出重点。