单独定义数组是不合法的,编译器会报错,但是如果定义在结构体中则编译器视为合法语法;定义示例如下所示:
struct str{
int len;
char s[0];
};
0长度数组有何意义呢?
0长度数组实质上就是指长度为0的数组,在结构体中它不占用内存空间。
在控制台输出上述结构体的大小可以得到如下结果:
printf("sizeof(str) = %ld\r\n", sizeof(struct str));
输出结果如下:
我们可以对比一下下面的结构体:
struct sstr {
int len;
char* s;
};
其输出结果打印输出大小如下:
由此可见结构体中定义char型的指针和定义0长度的数组是有很大区别的,指针需要占用12个字节的内存用
于保存指针地址;而0长度数组则不需要保存地址,应为它的地址是固定的;那么它的地址指向哪里呢?
那么我们输出一下信息可以得出结论:
struct str str;
printf("&str.len = %d\r\n", &str.len);
printf("str.s = %d\r\n", str.s);
输出结果为:
由上图可知,str.len的地址与str.s的地址偏移了四个字节;由此可见0长度数组的首地址为数组上一成员地
址的偏移。
那么0长度的数组有什么作用呢?
0长度的数组没有规定数组的长度,因此数组的长度是任意的,可以申请连续的内存块构成结构体一个结构体。
在释放内存时,因为是连续的内存块,所以只需要free结构体就可以释放所有内存,而不会像指针一样,需要先释
放结构体内指针所指向的内存块再释放内存,否则会早场内存泄漏!
在多人合作完成项目时通常会有一种情况,就是同事A编写了某部分代码函数库供同事B使用,同事B调用同事A
的函数时返回的是结构体指针,同事B使用完指针需要释放结构体指针指向的内存;因同事B未注意到该结构体内存
在指针指向的另外一块内存块,所以同事B未free结构体内部指针指向的内存导致内存泄漏现象。
如使用0长度数组则可以申请连续的内存块,在释放内存是就不存在上述情况了。
完整代码示例如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct str{
int len;
char s[0];
};
struct sstr {
int len;
char* s;
};
int main(int argc, char** argv) {
printf("sizeof(sstr) = %ld\r\n", sizeof(struct sstr));
printf("sizeof(str) = %ld\r\n", sizeof(struct str));
struct str str;
printf("&str.len = %d\r\n", &str.len);
printf("str.s = %d\r\n", str.s);
struct str* pstr = NULL;
pstr = (struct str*)malloc(sizeof(struct str) + 10);
if (pstr != NULL) {
pstr->len = 10;
memset(pstr->s, 'a', pstr->len);
printf("%s\r\n",pstr->s);
free(pstr);
}
return 0;
}