c/c++柔性数组成员
柔性数组成员
定义和声明分离
#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
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++!。
疑问,为什么不管Test t和char str[] = "Hello c Hello c++!";定义在哪里,编译器都能把str放到Test t的下面。