linux 零长数组,GNU C中的零长数组

C语言没有STL,缺乏对动态长度字符串功能的支持;同时,C使用'\0'判断字符串的结尾,不具有二进制安全性。然而在程序开发时,我们可以通过自定义的方式,实现简易的动态长度字符串功能。

动态长度字符串结构定义如下:

struct DynamicBuffer

{

unsigned len; // 实际长度

unsigned free; // 剩余可用空间大小

char data[0]; // 实际内容

};

其中,较为少见的是DynamicBuffer结构中的最后一项——定义了长度为0的字符数组。零长数组是在GNU C中定义的一项功能:

Zero-length arrays are allowed in GNU C. They are very useful as the last element of a structure which is really a header for a variable-length object.

在其他环境中编译含有零长数组的代码可能会导致编译错误。

在DynamicBuffer的定义中,我们当然也可以用char*来保存字符串数据。但是,使用零长数组代替数组指针具有以下优势:

指针占用存储空间;而零长数组则不占用结构体空间。

使用指针需要初始化,使用时需要间接寻址;零长数组不需要初始化,内存地址和后面的元素地址相同,数组名可以直接当作指针使用。

程序测试用例如下:

#include

#include

#define LENGTH 5

struct DynamicBuffer1

{

unsigned len;

unsigned free;

char *data;

}__attribute((packed));

struct DynamicBuffer2

{

unsigned len;

unsigned free;

char data[0];

}__attribute((packed));

int main()

{

struct DynamicBuffer1 *b1;

struct DynamicBuffer2 *b2;

int i;

printf("DynamicBuffer1 length: %d\n",sizeof(struct DynamicBuffer1));

printf("DynamicBuffer2 length: %d\n",sizeof(struct DynamicBuffer2));

b1=(struct DynamicBuffer1*)malloc(sizeof(struct DynamicBuffer1));

b1->len=0;

b1->free=LENGTH;

b1->data=(char *)malloc(sizeof(char)*LENGTH + 1);

b1->data[0] = 100;

b1->free--;

b1->len++;

printf("\nb1->len=%d,b1->free=%d,*(b1->data)=%d\n",b1->len,b1->free,*b1->data);

printf("b1\t\t address: %p\n", b1);

printf("b1->len\t address: %p\n", &(b1->len));

printf("b1->free\t address: %p\n", &(b1->free));

printf("b1->data\t address: %p\n", b1->data);

b2=(struct DynamicBuffer2*)malloc(sizeof(struct DynamicBuffer2)+sizeof(char)*LENGTH + 1);

b2->len=0;

b2->free=LENGTH;

for(i=0;i

{

b2->data[i]=i;

b2->free--;

b2->len++;

}

printf("\nb2->len=%d,b2->free=%d\n",b2->len,b2->free);

printf("b2\t\taddress: %p\n", b2);

printf("b2->len\taddress: %p\n", &(b2->len));

printf("b2->free\taddress: %p\n", &(b2->free));

printf("b2->data\taddress: %p\n", b2->data);

free(b1->data);

free(b1);

free(b2);

}

用例输出:

DynamicBuffer1 length: 16

DynamicBuffer2 length: 8

b1->len=1,b1->free=4,*(b1->data)=100

b1 address: 0x1ae7010

b1->len address: 0x1ae7010

b1->free address: 0x1ae7014

b1->data address: 0x1ae7030

b2->len=5,b2->free=0

b2 address: 0x1ae7050

b2->len address: 0x1ae7050

b2->free address: 0x1ae7054

b2->data address: 0x1ae7058

可见,通过零长数组定义的DynamicBuffer2占用的内存空间只有8个字节(两个整形变量的空间),且data数组地址紧邻DynamicBuffer2的内存地址。Redis的SDS API也使用了类似的方式,提供了二进制安全的动态长度字符串功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值