结构体—C语⾔中不定长结构体的使⽤
1、结构体的定长表⽰
C语⾔中结构体的使⽤基本上都是定长的,就如以下这种:
typedef struct
{
int a;
int b;
char c[100];
double d;
}STRU;
2、结构体的不定长表⽰
2.1、指针形式
但在很多的场景下,结构体的定义成不定长反⽽更容易解决问题,最典型的就是需要通过Socket发送⼀个结构体数据,但是结构体中包含了⼀个不定长的信息。可以采⽤以下⽅式来定义结构体:
typedef struct
{
int  a;
char *b;
char *c;
}STRU;
对于该种类型的结构体可以采⽤以下两种⽅式来申请并分配内存:
1)、直接分配
char b[] = "ahsdggc adgfas";
char c[] = "asjdhvbaegegfgasdjv";
int len = sizeof(STRU);
int len_b = strlen(b)+1;    //+1是因为字符串有⼀个字节存放'\0'
int len_c = strlen(c)+1;
STRU *stru = (STRU *)malloc(len + len_b + len_c);
memset(stru, 0, len);
printf("Before - STRU 的地址为:%x \n", stru);
printf("Before - STRU_B 的地址为:%x \n", stru->b);
printf("Before - STRU_C 的地址为:%x \n", stru->c);
stru->b = (char *)stru + len; //重新分配 stru->b 的地址
stru->c = stru->b + len_b;  //重新分配 stru->c 的地址
printf("After - STRU 的地址为:%x \n", stru);
printf("After - STRU_B 的地址为:%x \n", stru->b);
printf("After - STRU_C 的地址为:%x \n", stru->c);
strcpy(stru->b, b);    //将 b 的内容复制到 stru->b
strcpy(stru->c, c);    //将 c 的内容复制到 stru->c
cout << ">>> b: " << stru->b << endl;
cout << ">>> c: " << stru->c << endl;
运⾏的结果如下所⽰:
2)、间接分配
还有另外⼀种分配的⽅式:
char b[] = "ahsdggc adgfas";
char c[] = "asjdhvbaegegfgasdjv";
int len = sizeof(STRU);
int len_b = strlen(b)+1;    //+1是因为字符串有⼀个字节存放'\0'
int len_c = strlen(c)+1;
STRU *stru = (STRU *)malloc(len);
memset(stru, 0, len);
char *cb = (char *)calloc(0, len_b); // 申请 len_b 长的内存并初始化为0
memcpy(cb, b, len_b);    // 将 b 的内容复制到 cb 中
char *cc = (char *)calloc(0, len_c); // 申请 len_c 长的内存并初始化为0
memcpy(cc, c, len_c);    // 将 c 的内容复制到 cc 中
printf("Before - STRU 的地址为:%x \n", stru);
printf("Before - STRU_B 的地址为:%x \n", stru->b);
printf("Before - STRU_C 的地址为:%x \n", stru->c);
printf("Before - cb 的地址为:%x \n", cb);
printf("Before - cc 的地址为:%x \n", cc);
stru->b = cb;
stru->c = cc;
printf("After - STRU_B 的地址为:%x \n", stru->b);
printf("After - STRU_C 的地址为:%x \n", stru->c);
printf("After - cb 的地址为:%x \n", cb);
printf("After - cc 的地址为:%x \n", cc);
cout << ">>> b: " << stru->b << endl;
cout << ">>> c: " << stru->c << endl;
下图为验证的结果:
以上两种⽅式,⼀个是在申请结构体的内存时也分配字符串长度的内存;还有⼀种是先分配结构体的内存,然后再申请结构体长度的内存,然后通过地址赋值的⽅式使结构体中的元素指向那些内存;
2.2、空数组⽅式
但是还有⼀种形式的结构体:
sizeof 指针
typedef struct
{
int a;
int b;
char c[0];
}STRU;
在上⾯的定义中,char c[0]定义了⼀个长度为0的字符串数组,此时,在结构体中实际上只包含了a和b的地址空间,即sizeof(STRU)== 8,
此时c被当成⼀个指针,指向了结构体后⾯的内存地址的起始地址,c = &stru + sizeof(STRU),如下所⽰:
struct test3{
int a;
int b;
char c[0]; //不占⽤结构体的内存地址,此时c指向的就是结构体后⾯的内存空间的起始地址
};
test3 t3;
test3* pt3 = &t3;
printf("t3 address: %x\n", pt3);
printf("t3.c address: %x\n", t3.c);
cout << "sizeof(test3) = " << sizeof(test3) << endl; //8
最终输出结果为:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。