柔性数组成员
程序员文章站
2022-03-10 23:12:08
柔性数组成员 定义和声明分离 结构体里有指向字符串指针 结构体里如果有指向字符串指针,就会发生字符串在结构体的外面,不能由结构体来统一管理。 解决办法: 上面的代码有个弊端,就是访问那个str时,需要使用不容易理解的tp+1,改进如下。 为什么,虽然没有对t.pc赋值,但是打印出了正确的数据呢? 方 ......
柔性数组成员
定义和声明分离
#include <stdio.h> //只是告诉编译器,当编译到使用到这个函数的的代码时,虽然还没有找到函数定义的实体,但是也让它编译不出错误。 extern int fun(int a); extern int x; int x; int main(){ //在这行调用fun函数,但是编译器只找到了声明,没有找到fun的定义,所以编译不出错误,编译器在后面找到了fun函数的定义实体,所以运行没有问题。 fun(10); //在这行使用全局变量x,但是编译器只找到了声明,没有找到x的定义,所以编译不出错误,编译器在后面找到了全局变量x的定义实体,所以运行没有问题。 x = 22; } int fun(int b){ printf("b = %d\n",b); return b; } 运行结果: b = 22
结构体里有指向字符串指针
结构体里如果有指向字符串指针,就会发生字符串在结构体的外面,不能由结构体来统一管理。
#include <stdio.h> struct Test{ int a; long b; char* c; }; int main(){ //结构体里如果有指向字符串指针,就会发生字符串在结构体的外面,不能有结构体来统一管理。 char *str = "asd"; struct Test t; t.c = str; printf("%s\n", t.c); }
解决办法:
#include <stdio.h> #include <malloc.h> #include <string.h> typedef struct Test{ int a; long b; } Test; int main(){ char* str = "i am out of struct Test"; //sizeof(Test)结构体需要字节数,strlen(str)是str需要的字节数,最后的加1是'\0'。这样一来,就相当于只用指针tp,就既可以控制结构体里面的成员,也可以控制结构体外面的字符串。 Test* tp = (Test*) malloc(sizeof(Test) + strlen(str) + 1); tp->a = 10; tp->b = 11; strcpy((char*)(tp+1), str); printf("%s\n", (char*)(tp+1)); free(tp); }
上面的代码有个弊端,就是访问那个str时,需要使用不容易理解的tp+1,改进如下。
#include <stdio.h> typedef struct Test{ int a; long b; char pc[0]; }Test; int main(){ int a; long b; long c; //不管Test t放在哪行,t.pc都指向下面的str Test t; long dd; char str[] = "Hello c Hello c++!"; long ee; //非常的神奇,虽然没有对t.pc赋值,但是打印出了正确的数据。 printf("%s\n",t.pc);//Hello c Hello c++! }
为什么,虽然没有对t.pc赋值,但是打印出了正确的数据呢?
方法里声明的局部成员,存放在栈区,编译器把数组str放到了,Test t的下面,而且Test的成员pc还是0空间的数组,也就是不占用内存空间,所以pc内存地址正好和str的内存地址相同了,所以即使不对t.pc赋值,也能正确打印出Hello c Hello c++!。但是如果用char *str = "Hello c Hello c++!";的方式定义str,str就是一个常量了,就不会存放在栈区了,所以是无法被pc成员访问的。
疑问,为什么不管Test t和char str[] = "Hello c Hello c++!";定义在哪里,编译器都能把str放到Test t的下面。
因为str的占用的空间在main函数里是最大的,所以放到了栈的最底下,Test t占用的空间第二大所以放到了str的上面,所以t.pc指向了str,如果str占用的空间小,就不能保证t.pc指向str了。
C语言局部变量在内存栈中的顺序:
柔性数组
#include <stdio.h> #include <malloc.h> typedef struct Test{ int i; int ary[0]; }Test; int main(){ int len; scanf("%d", &len); Test* t = (Test*)malloc(sizeof(Test) + (sizeof(int) * len)); for(int i = 0; i < len; ++i){ t->ary[i] = i + 1; } for(int j = 0; j < len; ++j){ printf("%d ",t->ary[j]); } printf("\n"); free(t); }