关于指针的一个小疑点有关问题
关于指针的一个小问题问题
swapd (int *p1,int *p2)
{ int *p; /*指向交换:即交换指针变量本身的值,空间的地址*/
p=p1;
p1=p2;
p2=p;
}
main()
{ int a=10,b=20,*q1=&a, *q2=&b;
printf("a=%d, b=%d\n", a, b);
swapd(q1,q2); /*交换指向*/
printf("a=%d, b=%d\n", a, b);
}
为什么a,b的值没交换
------解决方案--------------------
这是困扰很多人的问题。值得一提的是,C语言中实参变量和形参变量之间的数据传递是单向的“值传递”方式。指针变量作函数参数也要遵循这一原则。不可能通过调用函数来改变实参指针变量的值,但可以改变实参指针变量所指变量的值。这一点在谭浩强老师的《C程序设计》第三版中228页有明确例题,你可以参考一下。具体到本题,稍加改动swapd函数即可。
swapd (int *p1,int *p2)
{ int p; /*定义中间存值变量,int型*/
p=*p1;
*p1=*p2;
*p2=*p;
}
------解决方案--------------------
2个要点:
1. 实参向形参拷贝是按值拷贝,即存储了什么就拷贝什么.
例如: int *p,int *q; p,q 都是用来装地址的变量, 所以 swap(int *p), swap(q),
是把q存储的地址传递给p, p存储了与q相同的地址,但是p与q是两个不同的变量,它们存储的内容相同而已.
2.注意形参的运算是否对实参造成影响.
还拿1里的来说, p存储了与q同样的地址, 那么通过*p一定可以访问这个地址里存的东西,也可以修改它.
但是如果你企图给q所指的地址动态开辟一段内存,你也许会这样做:
swap(int *p)
{p=mallco.....}
然后你会调用: swap(q);
会怎样呢? q存储的地址给了p,p与q存储了相同的地址, 你在内存中malloc了一段内存,malloc返回首地址赋值给p,现在p内存的地址是新开辟的地址,q内存的地址还是原先的地址, 当你在主函数里试图访问刚开辟的内存的时候,你也许会这么做: *q=2; 但是呢? q并没有指向新的内存,只是函数里的形参p指向了那段内存.
所以,如果你想传入一个指针变量,并让这个指针变量指向新开辟的内存,而不是像上边那样,你该怎么做呢?
swap(int *&p)
{p=malloc.........} 这样,你调用swap(q),q这个变量被引用进去,malloc返回的首地址赋值给q,你就可以直接在主函数里使用q访问新的内存了.
另一种方法,一样可以处理这个问题:
swap(int **p)
{*p=malloc.......} 然后,你在main里这样: int *q; swap(&q);
你的目的是想给将开辟的空间的首地址赋值给q存起来。你现在这样做,把q这个变量的地址传进去,而不是将q指向的地址赋值给形参。 现在把q这个变量的地址传进去, p存储了q的地址,而不是q指向的地址.
现在*p就是q这样变量了, 我们用malloc返回内存首地址赋值给*p存储起来,就等同于把malloc的地址赋值给q了.
是不是很神奇?
------解决方案--------------------
swapd (int *p1,int *p2)
{ int *p; /*指向交换:即交换指针变量本身的值,空间的地址*/
p=p1;
p1=p2;
p2=p;
}
在主函数中调用swapd,把q1(&a),q2(&b),传给p1,p2;
此时,p1与q1都指向a的地址;p2与q2都b的地址;
接着执行:p=p1; p1=p2; p2=p;
此时只是交换了 p1与p2它倆指向的地址,既p1指向了b的地址,既p2指向了a的地址;
不过,这与q1,q2有什么关系呢,既q1仍指向a,q2仍指向b;
再啰嗦一点,就是,此时: q1与p2指向a; q2与p1指向b;
接着,调用结束,p1,p2释放掉。
可以看下,下面的代码:
int a=10,b=20;
int *q1=&a, *q2=&b; /*定义成外部变量吧,便于说明*/
void swapd (int *p1,int *p2)
{ int *p;
p=p1;
p1=p2;
p2=p;
printf("执行swapd:\n");
printf("交换的是p1与p2: a=%d, b=%d\n", *p1, *p2);
printf("而此时的q1与q2仍是: *q1=%d, *q2=%d\n", *q1, *q2); /*加这一句printf,你就看出来了,自定义函数是改变了形参指针变量的值*/
return ;
}
main()
{
printf("起始:a=%d, b=%d\n\n", a, b);
swapd(&a,&b); /*交换指向*/
printf("\n\n执行swapd后:*q1=%d, *q2=%d\n", *q1, *q2);
}
swapd (int *p1,int *p2)
{ int *p; /*指向交换:即交换指针变量本身的值,空间的地址*/
p=p1;
p1=p2;
p2=p;
}
main()
{ int a=10,b=20,*q1=&a, *q2=&b;
printf("a=%d, b=%d\n", a, b);
swapd(q1,q2); /*交换指向*/
printf("a=%d, b=%d\n", a, b);
}
为什么a,b的值没交换
------解决方案--------------------
这是困扰很多人的问题。值得一提的是,C语言中实参变量和形参变量之间的数据传递是单向的“值传递”方式。指针变量作函数参数也要遵循这一原则。不可能通过调用函数来改变实参指针变量的值,但可以改变实参指针变量所指变量的值。这一点在谭浩强老师的《C程序设计》第三版中228页有明确例题,你可以参考一下。具体到本题,稍加改动swapd函数即可。
swapd (int *p1,int *p2)
{ int p; /*定义中间存值变量,int型*/
p=*p1;
*p1=*p2;
*p2=*p;
}
------解决方案--------------------
2个要点:
1. 实参向形参拷贝是按值拷贝,即存储了什么就拷贝什么.
例如: int *p,int *q; p,q 都是用来装地址的变量, 所以 swap(int *p), swap(q),
是把q存储的地址传递给p, p存储了与q相同的地址,但是p与q是两个不同的变量,它们存储的内容相同而已.
2.注意形参的运算是否对实参造成影响.
还拿1里的来说, p存储了与q同样的地址, 那么通过*p一定可以访问这个地址里存的东西,也可以修改它.
但是如果你企图给q所指的地址动态开辟一段内存,你也许会这样做:
swap(int *p)
{p=mallco.....}
然后你会调用: swap(q);
会怎样呢? q存储的地址给了p,p与q存储了相同的地址, 你在内存中malloc了一段内存,malloc返回首地址赋值给p,现在p内存的地址是新开辟的地址,q内存的地址还是原先的地址, 当你在主函数里试图访问刚开辟的内存的时候,你也许会这么做: *q=2; 但是呢? q并没有指向新的内存,只是函数里的形参p指向了那段内存.
所以,如果你想传入一个指针变量,并让这个指针变量指向新开辟的内存,而不是像上边那样,你该怎么做呢?
swap(int *&p)
{p=malloc.........} 这样,你调用swap(q),q这个变量被引用进去,malloc返回的首地址赋值给q,你就可以直接在主函数里使用q访问新的内存了.
另一种方法,一样可以处理这个问题:
swap(int **p)
{*p=malloc.......} 然后,你在main里这样: int *q; swap(&q);
你的目的是想给将开辟的空间的首地址赋值给q存起来。你现在这样做,把q这个变量的地址传进去,而不是将q指向的地址赋值给形参。 现在把q这个变量的地址传进去, p存储了q的地址,而不是q指向的地址.
现在*p就是q这样变量了, 我们用malloc返回内存首地址赋值给*p存储起来,就等同于把malloc的地址赋值给q了.
是不是很神奇?
------解决方案--------------------
swapd (int *p1,int *p2)
{ int *p; /*指向交换:即交换指针变量本身的值,空间的地址*/
p=p1;
p1=p2;
p2=p;
}
在主函数中调用swapd,把q1(&a),q2(&b),传给p1,p2;
此时,p1与q1都指向a的地址;p2与q2都b的地址;
接着执行:p=p1; p1=p2; p2=p;
此时只是交换了 p1与p2它倆指向的地址,既p1指向了b的地址,既p2指向了a的地址;
不过,这与q1,q2有什么关系呢,既q1仍指向a,q2仍指向b;
再啰嗦一点,就是,此时: q1与p2指向a; q2与p1指向b;
接着,调用结束,p1,p2释放掉。
可以看下,下面的代码:
int a=10,b=20;
int *q1=&a, *q2=&b; /*定义成外部变量吧,便于说明*/
void swapd (int *p1,int *p2)
{ int *p;
p=p1;
p1=p2;
p2=p;
printf("执行swapd:\n");
printf("交换的是p1与p2: a=%d, b=%d\n", *p1, *p2);
printf("而此时的q1与q2仍是: *q1=%d, *q2=%d\n", *q1, *q2); /*加这一句printf,你就看出来了,自定义函数是改变了形参指针变量的值*/
return ;
}
main()
{
printf("起始:a=%d, b=%d\n\n", a, b);
swapd(&a,&b); /*交换指向*/
printf("\n\n执行swapd后:*q1=%d, *q2=%d\n", *q1, *q2);
}