首先记录下时间吧,@2016-08-18 23:26:22,这段时间看了同事的3本经典的书,《c缺陷和陷阱》,《c和指针》和《c专家编程》,感觉指针说的最多,多多少少还是有点领悟,记录下自己对指针的心得吧。
1.很多时候多说指针和数组是等效的。这句话是有条件的,由于最近在看c++方面的资料(c现在工作不好找啊),有了新的理解。
简单的来说,指针是一个间接寻址,而数组是直接寻址,在内存中,指针需要去一次地址后才能取到数据,而数组在内存中就是地址,直接根据地址就可以取到数据。所以在作为参数传递到函数中时,带入指针和带入数组,这个是等价的,因为传入的都是地址。这里我仔细想了想,某种意义上,指针也是传值操作,只不过类型是一个TYPE *而已,传入的是指向的那个地址(p的内容,也就是p的指向,也就是数据的地址,这里指针可以有很多理解,每段时间的理解都不一样,反正就是一个变量,存的是一个数据块的地址,指针根据这个地址去取数据)。
2.看高质量的c及c++编程指南--指针参数是如何传递内存的,这个好纠结,真的好纠结,我看完了,还是不敢说自己完全理解,只能记录自己理解的部分。
首先一个二级指针的描述吧
pp --> p --> data in Mem
char *p = NULL;
p = (char *) malloc(10);
char **pp = NULL;
pp = &p;
其次是一个传值与传地址的理解吧,传值就是数据一个copy,传址就是变量在内存中地址传进去,很明显,可以改变地址里的内容,因而传指针和传数组都是能够改变传入的值的。
#include <stdio.h> void InPt(char *p) { printf("InPt p=[%s] *p=[%c] &p = [%d] ", p, *p, &p); } void InArr(char p[]) { printf("InArr p=[%d] p[0]=[%c] &p[0] = [%d] ", p, p[0], &p[0]); } int main(void) { printf("Hello World! "); char *p1 = "test";//这个是指向常量,分配在静态数据区,妄图改变是不可行的。 //*p1 = 'C'; error here char arr[5]= "this"; char *p = arr; printf("Main InArr arr=[%d] arr[0]=[%c] &arr[0] = [%d] ", arr, arr[0], &arr[0]); printf("Main InPt p=[%s] *p=[%c] &p = [%d] ", p, *p, &p); printf("***** "); InArr(arr); InPt(p); printf("%s ", p); return 0; }
/*************Result:****************/
Hello World!
Main InArr arr=[2752167] arr[0]=[t] &arr[0] = [2752167]
Main InPt p=[this] *p=[t] &p = [2752160]
*****
InArr p=[2752167] p[0]=[t] &p[0] = [2752167]
InPt p=[this] *p=[t] &p = [2752144]
this
/*************end:****************/
可以看到 &p = [2752160] &p = [2752160] 带进去的值是一样,但是装这个值的盒子(内存)却不一样,因为编译器为函数的参数制作值copy,所以我理解,传指针和传数组都是传‘值’,只不过这个值特殊而已,是一个地址而已。
林博士在《高质量的c及c++编程指南》举得例子:
void GetMemory(char *p, int num)
{
p = (char *)malloc(sizeof(char) * num);
}
void Test(void)
{
char *str = NULL;
GetMemory(str, 100); // str 仍然为 NULL
strcpy(str, "hello"); // 运行错误
}
分析下GetMemory(str, 100)中str是一个指针,指针是间接取值,自身也占4个字节的空间,所以Test中的&str和GetMemory中的&p是两个盒子,只不过两个盒子中的东西一样而已,这某种意义上是传值,传的是盒子里的内容,指针这里很容易弄乱,至少我是这样的。其返回的任然是装指针的那个盒子,而这盒子并不是和主函数中的盒子一样,所以,分配不成功。
解决方法1:书中的一个是二级指针,带入chap **p,这样的话把盒子的地址传进去,在带出来.一级p指向data,其地址是二级p的内容,很明显二级就是传的一级指针的地址。
方法2:返回值传递动态内存
char *GetMemory3(int num)
{
char *p = (char *)malloc(sizeof(char) * num);
return p;
}
void Test3(void)
{
char *str = NULL;
str = GetMemory3(100);
strcpy(str, "hello");
cout<< str << endl;
free(str);
}
在堆上申请一块地址,p指向其,并返回p的地址。而后str指向这块地址,ok。
好了睡觉去。