标签:
在研究按值传递机制时,发现一些模糊的概念。就是在对一个原本的(指针)变量重新给定另外一个值时,会不会改变这个变量原本所在的内存位置(即地址)。因此,决定深入研究一下。而且这也是必要的。
1 //验证变量在被赋值(以及被重赋值)时原本分配的内存地址是否会改变。 2 3 #include <stdio.h> 4 5 int main(void) 6 { 7 int a;//声明a,即已经给a分配一个内存地址 8 printf("声明a时的地址:%p\n", &a); 9 10 a = 1; //初始化a 11 printf("The address of origin: %p\n", &a);//输出a=1时的地址 12 13 //int a = 2; ----> 不能以这种方式对a重新赋值. 否则会产生错误:‘a’重定义 14 scanf("%d", &a);//对a重新赋值。 15 printf("The address of later: %p\n", &a);//被重新赋值后的地址 16 17 return 0; 18 }
运行结果:声明a时的地址:0x7ffc3cabc31c
The address of origin: 0x7ffc3cabc31c
2 ->这个2是我输入的。
The address of later: 0x7ffc3cabc31c
结论:在声明时给变量a划分的地址,会在变量作用域内一直保持不变。原本a=1时,地址是xxx,在第a重新赋值时,会先将a内的数删除,然后再将新的数放进去,这个新的数的地址还是xxx。即地址一直不变,变得是这个地址里的数。(就像租房,有效期内房子一直不变,变的是住的人)
1 //验证对指针所指向的值重新赋值时,指针是否会改变。 2 #include <stdio.h> 3 4 int main(void) 5 { 6 int *p = NULL; 7 int a = 1; 8 printf("p指针存储的地址:%p\n", p); 9 printf("p指针的地址:%p\n", &p); 10 11 p = &a; 12 printf("p指针存储的a地址:%p\n", p); 13 printf("p指针的地址:%p\n", &p); 14 15 *p = 2; 16 printf("p指针存储的对a重新赋值时地址:%p\n", p); 17 printf("p指针的地址:%p\n", &p); 18 19 int b = 2; 20 p = &b; 21 printf("p指针存储的b地址:%p\n", p); 22 printf("p指针的地址:%p\n", &p); 23 24 return 0; 25 }
运行结果:p指针存储的地址:(nil)
p指针的地址:0x7ffe95265668
p指针存储的a地址:0x7ffe95265664
p指针的地址:0x7ffe95265668
p指针存储的对a重新赋值时地址:0x7ffe95265664
p指针的地址:0x7ffe95265668
p指针存储的b地址:0x7ffe95265660
p指针的地址:0x7ffe95265668
分析:有点乱,但没关系,一句一句看。在将指针指向NULL时,实质上并没有给指针p分配存储的地址。即p不指向任何地址。所以输出了:p指针存储的地址:(nil)。而p本身的地址(即存储p的地址)为0x7ffe95265668,在整个main函数内,存储p指针的地址其实是一直不变的。这在第1点可以知道原因。p = &a这句是将p指向a所在的地址。*p = 2这句是通过*p对a重新赋值。期间,p存储的地址保持一致,即:0x7ffe95265664。p = &b这一句将p重新指向一个新的变量了。打个比方:(指针p包含的)地址:a本来是你家,后来你搬家了,那么地址肯定改变了,所以(指针p包含)地址也改变了。由0x7ffe95265664这个原本是指向a的地址 变为 指向b的地址:0x7ffe95265660。
1 #include <stdio.h> 2 3 void change_int(int *a); 4 5 int main(void) 6 { 7 int a = 2; 8 printf("a本来的地址: %p\n", &a); 9 10 change_int(&a); 11 printf("被调用后a = %d\n", a); 12 printf("a后来的地址: %p\n", &a); 13 14 return 0; 15 } 16 17 void change_int(int *a) 18 { 19 printf("在被调用函数里面a的地址:%p\n", &a); 20 *a = 3; 21 } 22 ~
输出结果:a本来存储的地址: 0x7ffc75a6f48c
1 #include <stdio.h> 2 3 int main(void) 4 { 5 char *a = "abc"; 6 scanf("%s",a);//这句目的是调用scanf函数对a重新赋值。 7 printf("%s",a); 8 return 0; 9 }//这个代码的目的是将a中的abc变成sss
这个代码可以编译连接成功。但是当输入:sss 按回车时,出现了这么一个错误:Segmentation fault (核心已转储),这个错误是由于地址出错。
1 #include <stdio.h> 2 3 void change_piont(char **a);//用于改变指针所存储的值的函数。 4 void change_int(int *b);//用于改变变量的值的函数。 5 void change_array(char *c, int n); 6 7 int main(void) 8 { 9 char *a = "absdefg"; 10 printf("a = %s\n", a); //输出absdefg 11 change_piont(&a);//将指针变量a的地址作为变元 12 printf("%s\n", a);//输出ddd,即改变指针a存储的值成功。 13 14 int b = 2; 15 printf("origin = %p\n", &b);//b原来的地址:xxx 16 17 change_int(&b);//将变量b的地址作为变元。 18 printf("(later)b = %d\n",b);//调用后b的值,输出为3 19 printf("later = %p\n", &b);//经过调用一回后,b的地址:还是xxx 20 21 22 char c[5] = "abcd";//数组c本来的值:abcd 23 change_array(c,5); 24 printf("c = %s\n",c);//输出结果:abcf 25 26 return 0; 27 } 28 29 void change_piont(char **a) 30 { 31 char *b = "ddd"; 32 *a = b; 33 // printf("%s\n", *a); 34 } 35 36 void change_int(int *b) 37 { 38 printf("chang_int -> the address of b = %p\n", &b);//这个地址和原本b的地址不一样,说明它是一个副本。 39 *b = 3; 40 } 41 42 void change_array(char *c, int n) 43 { 44 c[3] = ‘f‘; 45 } 46 /****************************************************** 47 * 原本输出结果: 48 * a = absdefg 49 * ddd 50 * origin = 0x7ffc5c289f84 51 * chang_int -> the address of b = 0x7ffc5c289f58 52 * (later)b = 3 53 * later = 0x7ffc5c289f84 54 * c = abcf 55 * ****************************************************/
大多数都可以在注释上看明白,这里我重点要说这句(11句):change_piont(&a);//将指针变量a的地址作为变元。还记得上面的疑问吧?a是一个地址吧?那么我给被调用函数传递的是a地址啊,为什么不能成功改变a存储的值(即abs)。注意这里调用函数括号内与上一个代码中(scanf("%s",a))括号内的a有什么不同,多了一个取址符:&
1 #include <stdio.h> 2 3 void change_piont(char **a); 4 5 int main(void) 6 { 7 char *a = "abc"; 8 printf("a本来的地址:%p\n", &a); 9 printf("a本来存储的地址:%p\n", a); 10 11 change_piont(&a); 12 printf("调用后a的地址:%p\n",&a); 13 printf("调用后a存储的地址:%p\n",a); 14 15 printf("a = %s\n",a); 16 return 0; 17 } 18 19 void change_piont(char **a) 20 { 21 printf("在被调用函数内a的地址: %p\n",&a); 22 *a = "sss"; 23 24 } 25 /************************************************ 26 * result: 27 * a本来的地址:0x7ffe6bbd2088 28 * a本来存储的地址:0x400680 29 * 在被调用函数内a的地址: 0x7ffe6bbd2068 30 * 调用后a的地址:0x7ffe6bbd2088 31 * 调用后a存储的地址:0x400725 32 * a = sss 33 * **********************************************/
看结果已经很清楚了。a本来的地址就是指针a本身的地址。a本来存储的地址就是本来存储在a指针的地址。举个例子吧。*a = &b。a本来的地址就是:&a。a本来存储的地址就是:&b。
深入研究:对变量以及指针重新赋值过程中原本的地址是否会改变。(按值传递机制的深入)
标签:
原文地址:http://www.cnblogs.com/busui/p/5690789.html