有些基础的问题,看似很简单,平时也没怎么注意,但是理解不深刻的话,可能就在关键的地方出错了,导致严重的后果。C语言的掌握是个实践的过程,单靠掌握一些基本的东西,不实践的话,永远也不能理解其中的精髓。也只有在实践中来能深刻理解某些看似简单的原理。
1 关于结构体类型的指针的理解:
1.1首先要理解指针的本质,在32位系统中,可以再指针变量看成int型的变量,占4个字节,不管指针变量前面如何的修饰,那只是对指针变量所指向的变量的类型的说明,跟指针是没有多大关系的,指针还是占4字节的空间。
1.2 指针变量的使用一定是和具体的对象绑定在一起的(这里的对象指的是具体的内存空间,可以是简单变量的内存空间,可以使结构变量的内存空间,也可以使堆空间等)
1.3 首先要说明结构体类型的指针是没有成员的,成员是相对结构体变量来讲的。定义了结构体类型的指针,肯定就要有对应的结构体变量与之关联。
1.4 对于结构体成员中还有其他结构类型的指针变量,且同时开辟的两个结构类型大小的堆空间是,应该先释放结构成员指针指向的堆空间 再释放外面的指针变量指向的堆空间。如果顺序出错,就会出现内存泄露的问题。
例如:定义两个结构体:
structB{
int c;
};
structA{
int a;
int b;
struct B *p;
};
structA *pa = malloc(sizeof(struct A));
pa->p= malloc(struct B);
/**释放顺序**/
free(pa->p);
free(pa);
2对函数返回值的理解:
首先函数的调用是要开辟栈空间的,函数结束后,开辟的空间要被操作系统回收,函数内部定义的变量就不能在继续使用。函数返回时只能返回局部变量的值(函数内部定义的变量),不能返回局部变量的地址。因为保存局部变量的值的地址空间已经被系统回收了,就不能再使用了。
应该说所有函数的返回都是变量的值的返回!!说到这里可能会有朋友质问了,函数还可以返回指针呢?指针不就是地址么?需要说明的是,指针是地址,但它也是一个数值嘛,没有什么特殊的地方。返回指针的情况无非就两种:
返回全局变量的指针(地址),返回堆空间的指针(地址)。这些地址还不是指针变量的值!!!所以话说回来,函数返回的本质还是变量的值。只不过这个变量可能是普通变量,也可能是指针变量。(指针变量的值就是一段内存地址)。
举个例子:
struct B *f1()
{
structA a;
struct A *pa = &a;
pa->p = malloc(struct B);
pa->p->c = 100;
/**函数结束后要想获取堆空间中c的值,只能返回pa->p指针变量(即堆的地址),不能返回pa.因为指向的存放变量a的地址空间已经释放。pa的值就是a的地址**/
return pa->p;
}