指针理解(续)

使用的测试程序:
#include <stdio.h>
#include <string.h>

int test_1(int * point)
{
     printf("point : %08x\n", point);
     point = malloc(512);
     printf("point : %08x\n", point);
     return 0;
}
int test_2(int ** point)
{
     printf("2_point: %08x\n", point);
     *point = malloc(512);
     printf("*point: %08x\n", *point);
     return 0;
}
int test_3(int *** point)
{
     printf("3_point:%08x\n", point);
     *point = malloc(512);
     printf("*3_point:%08x\n", *point);
     return 0;
}

int main(int arg, char **argv)
{
     int * p_1 = NULL;
     int **p_2 = NULL;
     int ***p_3= NULL;
     int s[1]  = {1};
     printf("p_1:%08x \n", p_1);
     printf("&p_1:%08x \n", &p_1);
     //printf("*p_1:%08x \n", *p_1);
     printf("p_2:%08x \n", p_2);
     printf("&p_2:%08x \n", &p_2);
     printf("p_3:%08x \n", p_3);
     printf("&p_3:%08x \n", &p_3);
     printf("s: %08x\n", s);
     printf("&s: %08x\n", &s);
     printf("=========================\n");
    //printf("*p_1:%08x \n", *p_1);//here generate segmention fault, bacause the p_1 is NULL
     //*p_2 = s;//here generate segmention fault, bacause the p_2 is NULL
     s[1] = (int)(&p_1);
     printf("s[1]:%08x\n", s[1]);
     p_2 = s;
     printf("start");
     printf("*p_2:%08x \n", *p_2);
     printf("**p_2:%08x \n", **p_2);

     printf("=========================\n");
     test_1(p_1);
     test_2(&p_1);
     test_3(&p_2);

     printf("p_1:%08x\n", p_1);
     printf("p_2: %08x\n", p_2);
     printf("p_3: %08x\n", p_3);
     while(1);
}

第一次记录:
p_1:00000000
&p_1:bfeee100
p_2:00000000
&p_2:bfeee0fc
p_3:00000000
&p_3:bfeee0f8
s: bfeee0f4
&s: bfeee0f4

=========================
s[1]:bfeee100
start*p_2:00000001
段错误



将 s[1] = (int)(&p_1);
修改为
 s[0] = (int)(&p_1);
第二次记录:
p_1:00000000 
&p_1:bf915ec0 
p_2:00000000 
&p_2:bf915ebc 
p_3:00000000 
&p_3:bf915eb8 
s: bf915eb4
&s: bf915eb4

=========================
s[1]:00000000
start*p_2:bf915ec0 
**p_2:00000000 

=========================
point : 00000000
point : 08994008
2_point: bf915ec0
*point: 08994210
3_point:bf915ebc
*3_point:08994418
p_1:08994210
p_2: 08994418
p_3: 00000000

由两次红色部分可知,二级指针相对于一级指针是访问了三次内存单元,
第一次访问p_2自己的内存单元,得到(&p_2)内存单元中的内容ctx1;
第二次访问内容ctx1指向的内存,带到(ctx1)内存单元中的内容ctx2;
第三次访问内容ctx2指向的内存,得到(ctx2)内存单元中的内容ctx3;
这个ctx3就是需要读取的数据。

由紫色部分知道,数组与指针变量是不一样的,
数组的名字表示的就是内存单元的地址,
指针变量的名字表示的是内存单元中的内容。
(为什么指针中的内容是四个字节也就是因为这个缘故,
因为内存地址在32位机上是四个字节。
但是并不是指针的内容都是四个字节,
这个要根据内存地址的字节数来判断。
不同机器可能有差异)

所以指针与数组有很大的差异。

这个也可以解释为什么
char *p = "hello word"
中*p = ‘H’是错误的,将造成段错误。
因为p中的内容是"hello word"的地址,
而这个地址是在rodata区,只读数据区
而*p也就表示rodata中的内存单元中的内容,
*p = ‘H’将向只读区写数据,是要出错的。

如果想向*p中写数据,
可以先修改p的值,(这个值要是能写入的内存单元地址)
然后再向*p中写入数据。
这个时候p已经不指向"hello word"的内存单元了。

你可能感兴趣的:(指针理解(续))