说这个话题之前,先来谈谈定长数组。
定长数组
定长数组就是长度固定数组。比如我们收发报文的缓冲区,采用定长数组去表示:
typedef struct
{
unsigned int meg_len;
char msg_data[MSG_LEN];
} MsgBuffer;
这里MSG_LEN是固定大小的,比如,MSG_LEN = 1024
;也就是说我们每次使用都至少要申请sizeof(int) + sizeof(char)*1024
=1028个bytes,但是如果我们收发包小于1024怎么办?岂不就浪费了内存,导致数组冗余吗!
怎么解决呢?最直接的办法就是做成指针结构体,如下:
typedef struct
{
unsigned int meg_len;
char *msg_data;
} MsgBuffer;
这样就可以解决了,申请内存大小 = sizeof(int)+sizeof(char*)
但是会带来其他问题,在使用时:
//内存申请
p_buffer = (MsgBuffer *)malloc(sizeof(MsgBuffer));
if(NULL != p_buffer){
p_buffer->msg_len = cur_len;
p_buffer->msg_data = (char*)malloc(sizeof(char *)*cur_len;
if(NULL != p_buffer->msg_data){
memcpy(p_buffer->data,data,cur_len);
}
}
//内存释放
free(p_buffer->data);
free(p_buffer);
p_buffer = NULL;
这里产生了新的问题,就是需要两次申请内存,需要分别的管理,就需要释放两次,一不小心忘记释放,就会造成内存泄露。
变长数组
变长数组(variable-length array),也简称VLA。
变长数组既数组大小待定的数组, C语言中结构体的最后一个元素可以是大小未知的数组,也就是所谓的0长度,所以我们可以用结构体来创建变长数组。
typedef struct
{
unsigned int meg_len; //至少包含一个成员
char msg_data[]; //变长数组成员必须是结构体最后一个
} MsgBuffer;
使用
//内存申请
p_buffer = (MsgBuffer *)malloc(sizeof(MsgBuffer) + sizeof(int) * cur_len);
if(NULL != p_buffer){
p_buffer->msg_len = cur_len;
memcpy(p_buffer->data,data,cur_len);
}
//内存释放
free(p_buffer);
p_buffer = NULL;
此时就只用管理一次。
-
用途
它的主要用途是为了满足需要变长度的结构体,为了解决使用数组时内存的冗余和数组的越界问题。 -
用法
在一个结构体的最后 ,声明一个长度为空的数组,就可以使得这个结构体是可变长的。对于编译器来说,此时长度为0的数组并不占用空间,因为数组名本身不占空间,它只是一个偏移量, 数组名这个符号本身代 表了一个不可修改的地址常量 (注意:数组名永远都不会是指针! ),但对于这个数组的大小,我们可以进行动态分配,对于编译器而言,数组名仅仅是一个符号,它不会占用任何空间,它在结构体中,只是代表了一个偏移量,代表一个不可修改的地址常量!