最近细读《Programming in C》,里面讲数组时讲到了“
变量长度数组”,说有的编译器支持这样的用法:
int i=10;
char buf[ i ];
我测试发现VC6是不支持这个的,但是GCC支持!我写了这样的测试代码,发现程序居然也支持i是负数,而且在负数的情况下,GCC的内存分配虽然怪异,但也是保证正确的。
#include <stdlib.h>
#include <stdio.h>
void fun(int i)
{
char kk = 'B';
char buf[ i ];
char mm = 'E';
printf("size :: %d %x -- %x\n", sizeof(buf), (size_t)buf, (size_t)&buf[i-1]);
buf[i-1] = 'a';
printf("\t\t\t buf[i-1]:%c\t %x:%c \t %x:%c \n", buf[i-1], (size_t)&kk, kk, (size_t)&mm, mm);
}
int main(int argc, char * argv[], char * envp[])
{
fun(2);
fun(3);
fun(4);
fun(1);
fun(0);
fun(-1);
fun(-10);
}
GCC安全的为负数长度的数组分配了空间,保证了这种数组的安全使用, 不会影响栈上的其他变量空间。
下面是输出:
size :: 2 bfbfec50 -- bfbfec51
buf[i-1]:a bfbfec7f:B bfbfec7e:E
size :: 3 bfbfec50 -- bfbfec52
buf[i-1]:a bfbfec7f:B bfbfec7e:E
size :: 4 bfbfec50 -- bfbfec53
buf[i-1]:a bfbfec7f:B bfbfec7e:E
size :: 1 bfbfec60 -- bfbfec60
buf[i-1]:a bfbfec7f:B bfbfec7e:E
size :: 0 bfbfec60 -- bfbfec5f
buf[i-1]:a bfbfec7f:B bfbfec7e:E
size :: -1 bfbfec60 -- bfbfec5e
buf[i-1]:a bfbfec7f:B bfbfec7e:E
size :: -10 bfbfec60 -- bfbfec55
buf[i-1]: bfbfec7f:B bfbfec7e:E
我的疑问:
0长度的数组有什么意义?
这个经过搜索资料,我已经知道了,参考:
http://bbs.chinaunix.net/viewthread.php?tid=854949 在产品级的软件开发中,这种“变量长度数组”有人应用吗?
嗯,我估计这种不通用的东西产品里应该很少用。尽量避免使用,增强移植性。
至于数组长度是负数的情况,我是这么想的:
GCC就像数学家发现自然数后又发现了负数那样,GCC为人们实现了负数数组长度,并告诉我们数组长度也可以是负数。
至于负数有什么物理意义,数学家先不管了;数组长度负数有什么实际意义,Gcc就不管了。
Quote:
引用第1楼yinx于2007-11-30 12:36发表的 :
变量mm的空间分配先于buf数组?
能对0长度数组或者负数长度数组的单元赋值吗?
风中帖的转过来回答第一个问题:我也不太清楚mm的空间分配是否先于buf,但是肯定的是在程序运行的时候分配,变量长度数组C99是不支持的,但是有些编译器支持如GCC;在标准 C 或者 C++ 中由于不支持 0 长度的数组,所以 int array[0]; 这样的定义是非法的。不过有些编译器的扩展功能支持 0 长度的数组。声明0长度数组也只是做一个地址标记。
第二个问题:从上面测试代码来看很明显如果用GCC, 0长度数组或者负数长度数组的单元赋值是成功的,但内存单元具体怎么实现不清楚
在 C 中,0 长度的数组的主要用途是用来作为结构体的最后一个成员,然后用它来访问此结构体对象之后的一段内存(通常是动态分配的内存)。由于其非标准性,在程序中尽量避免使用 0 长度的数组。作为替换,可以使用 C99 标准中的不完整数组来替换 0 长度的数组定义。
在工程中0长度数组:
int main(void)
{
struct student{
unsigned int ID;
char follow_info[0];
/*这里不能再有数据成员*/
} Ptr*;
int i = 100 ,count ;
Ptr = malloc(sizeof(struct student) + i);
for (count =0 ; count < i; ++count )
p->data[i] = 1;
}
[ 此帖被ljpdxj在2007-11-30 14:53重新编辑 ]