天天看点

结构体中的指针与零长度数组从汇编分析原因零长度数组存在的价值

0长度的数组在iso c和c++的规格说明书中是不允许的,但是由于gcc 预先支持c99的这种玩法,所以,“零长度数组”在gcc环境下是合法的。

先看下面两个例子。

pzerolengtharray.c

zerolengtharray.c

编译,运行如下

从上面的运行结果可以看出,sizeof的结果以及发生段错误的位置,均不相同。

生成汇编代码,分析如下

可以看到有

对于char s[0]来说,汇编代码用了leaq指令,leaq 4(%rax), %rdi

对于char*s来说,汇编代码用了movq指令,movq 8(%rax), %rdi

lea全称load effective address,是把地址放进去,而mov则是把地址里的内容放进去。

从这里可以看到,访问成员数组名其实得到的是数组的相对地址,而访问成员指针其实是相对地址里的内容(这和访问其它非指针或数组的变量是一样的)。

访问相对地址,程序不会crash,但是,访问一个非法的地址中的内容,程序就会crash。

第一,节省内存。从上面的例子中可以看出,零长度数组不占用内存空间,而指针却占用内存空间。

第二,方便内存释放。如果我们的代码是在一个给别人用的函数中,你在里面做了二次内存分配,并把整个结构体返回给用户。用户调用free可以释放结构体,但是用户并不知道这个结构体内的成员也需要free,所以你不能指望用户来发现这个事。所以,如果我们把结构体的内存以及其成员要的内存一次性分配好了,并返回给用户一个结构体指针,用户做一次free就可以把所有的内存也给释放掉。

第三,这样有利于访问速度。连续的内存有益于提高访问速度,也有益于减少内存碎片。

test.c

gdb调试如下

继续阅读