一、柔性数组
今天看了公司的代码,发现一个很奇怪的问题,后来自己写了类似代码,我先把代码贴出来吧。
#include<stdio.h> #include<string.h> #include<stdlib.h> typedef struct { char ucDstMac[6]; char ucSrcMac[6]; int usType; int usLen; char ucCode; char ucSeq; char ucSlot; char ucInfo[]; }DEV_CARD_MSG_S; int main(void) { int i = 0; DEV_CARD_MSG_S* DS1; char data[64]; DS1 = (DEV_CARD_MSG_S*)malloc(sizeof(DEV_CARD_MSG_S)); memset(data,0,sizeof(data)); DS1 = (DEV_CARD_MSG_S*)data; DS1-> ucCode = 'A'; DS1-> ucInfo[6] = 'B'; printf("DS1-> ucCode=%c DS1-> ucInfo[6]=%c ",DS1-> ucCode,DS1-> ucInfo[6]); for(i=0;i<64;i++) printf("data[%d]=%c ",i,data[i]); return 0; }
好奇怪啊,有木有,结构体中竟然定义了一个包含0个元素的数组,当时看到这里就晕晕的。后来查找了资料,才知道这就是传说中柔性数组,柔性数组一般应用在结构体中,数组大小可变的场合中。
我们分析上述程序,data是一个占64字节的字符数组,DS1 = (DEV_CARD_MSG_S*)这行代码相当于给DS1结构体分配了64字节的地址,而这个结构体中定义时只申请了23字节的地址,此时还省64-23=41字节的地址会全部分配给DEV_CARD_MSG_S结构体中的ucInfo数组,因此此时即使我们写出DS1->ucInfo[40]='D'也是合法的,因为我们为数组ucInfo申请了41字节的地址空间。
上述程序打印如下,只贴出一部分:
(二)指针赋值
我们看上面代码执行的结果,发现我们代码中只操作了DS1结构体指针,结果data数组的值也跟着变化了,而且地址是对应的。刚开始看到这种神奇的代码我也好好奇。我们看到程序中有这么一行代码:DS1 = (DEV_CARD_MSG_S*)data;这是指针之间的赋值,也就是说结构体DS1和data数组在内存中占用的地址是一样的。其实这个代码和下面这个是类似的,我们看下面的代码就可以很好地理解了。
#include<stdio.h> int main() { int *P = NULL; int a = 10; P = &a; *P =20; printf(" a = %d *P = %d ",a,*P); printf("&a = %p P = %p ",&a,P); return 0; }
程序执行结果如下:
我们看到,我们操作P指针也就是操作a变量,同时他们两个占用的内存地址是一样的。因此只要*P的值改变了,a的值也就跟着改变了。这个特点很重要,在工程中应用的还是蛮多的。