0长数组

原文地址:[Linux 系统编程] 0长数组 作者:crazyhadoop

零长数组
    在标准 C 或者 C++ 中由于不支持 0 长度的数组,所以 int array[0];
这样的定义是非法的。不过有些编译器(如GCC)的扩展功能支持 0 长度的数组。
    在 C 中,0 长度的数组的主要用途是用来作为结构体的最后一个成员,
然后用它来访问此结构体对象之后的一段内存(通常是动态分配的内存)。
由于其非标准性,在程序中尽量避免使用 0 长度的数组。作为替换,可以
使用 C99 标准中的不完整数组来替换 0 长度的数组定义。如:
        typedef struct _X {
            int a;
            char array[]; //不完整数组,因此不可以计算sizeof(X),无法编译通过
        } X;
    在GNU的gcc-4.4.0的官方指南中的5.14节Arrays of Length Zero一节中,写道:
        struct line {
            int length;
            char contents[0];
        };
        //...ommit code here
        struct line *thisline = (struct line *) malloc (sizeof (struct line) + this_length);
        thisline->length = this_length;
    这个用法主要用于变长Buffer,struct line的大小为4,
结构体中的contents[0]不占用任何空间,甚至是一个指针的空间都不占
(待会儿下面的示例代码会验证),contents在这儿只是表示一个常量指针,
这个特性是用编译器来实现的,即在使用thisline->contents的时候,这个指针
就是表示分配内存地址中的某块buffer,比如malloc (sizeof (struct line) + this_length)
返回的是0x8f00a40,thisline->contents指向的位置就是(0x8f00a40 + sizeof(struct line)),
而这儿sizeof(struct line)仅仅是一个int的四字节。
    对于这个用法,我们定义的结构体指针可以指向任意长度的内存buffer,这个技巧在
变长buffer中使用起来相当方便。为什么不把最后的contents直接定义为一个指针呢?
这儿的差别是这样的,如果定义为一个指针,它需要占用4Bytes,并且在申请好内存后
必须人为赋地址才可以。如果使用这个用法,这个常量指针不占用空间,并且无需赋值。
    但是,方便并不是绝对的,在释放分配的内存的时候,由于函数free会认为*thisline 只是
指向一个4字节的指针,即只会释放length的空间,而对于后面占据大头的buffer却视而不见,
这个就需要人为干预;而对于后面的声明指针的方式,则可以直接用Free(thisline->contents)
的方式释放掉分配的内存。
    如果将零长数组array换成指针*array来使用的话,指针必须重新分配一段内存之后才能使用,
那么当想要用socket发送结构体指针的时候,并不会将指针array申请的内存发送过去,
因为是不连续的,所以接受socket发送来的数据后,会发现该数据并不是自己想要的。
struct t
{
int a;
int arr[0];
};

int main()
{
printf("%d\n",sizeof(struct t));//4, arr[0] 不占用任何空间
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值