说明:笔者水平有限,这当做个人学习C语言的笔记,如有错误欢迎指出和讨论。
题目
求程序运行结果
#include<stdio.h>
void foobar(int a, int *b, int **c)
{
int *p = &a;
*p = 101;
*c = b;
b = p;
}
int main()
{
int a = 1;
int b = 2;
int c = 3;
int *p = &c;
foobar(a, &b, &p);
printf("a=%d, b=%d, c=%d, *p=%d\n", a, b, c, *p);
return (0);
}
答案
使用DEV C++运行,结果如下:
题解
为了方便理解,增加三行代码在“int *p = &c”后面
int *p_a=&a;
int *p_b=&b;
int **p_c=&p;
断点设置在“foobar(a, &b, &p);”,结果如图:
也就是a的地址为70fe04,b的地址为70fe00,c的地址为70fdfc。c的地址的地址为70fdf0,这里也可以看出双重指针的含义。
若把断点设置在“int *p = &a”,运行结果如图:
也就是函数foobar中的b为main中b的地址,c为main中c的地址的地址。
继续执行到“b=p”。如图:
a的值变成了101,因为p是指向a的指针,“*p = 101”改变了a的值。c的值没有变,改变的是c指向的变量的值,原本指向的是main函数中c的地址,变成了main函数中b的地址。foobar函数中b的值变成了70fdc0,即p的值,但这没有改变main中b的值。
因此实际改变的是地址,main中的a、b、c没变,p变成了b的地址,因此*p输出b。
如果修改一行,把"b=p"改成"*b = *p",才能改变b:
void foobar(int a, int *b, int **c)
{
int *p = &a;
*p = 101;
*c = b;
*b = *p;
}
运行结果:
还有最后一个问题,为什么a仍然是1而不是101,我们在"foobar(a,&b,&p)"后添加:
printf("&a=%x,&b=%x,&c=%x",&a,&b,&c);
运行结果:
实际上b的地址也没用发生改变,即使运行了"b = p"。
为了更直观的分析问题,运行如下代码:
#include<stdio.h>
void aa(int a)
{
a=2;
}
int main()
{
int a = 1;
aa(a);
//printf("a=%d, b=%d, c=%d, *p=%d\n", a, b, c, *p);
printf("a=%d",a);
return (0);
}
结果为1,即使aa函数中让a=2。
再运行如下代码:
void aa(int * a)
{
*a=2;
}
int main()
{
int a = 1;
aa(&a);
//printf("a=%d, b=%d, c=%d, *p=%d\n", a, b, c, *p);
printf("a=%d",a);
return (0);
}
运行结果:
通过指针来改变a的值,结果为2。
同理,指针值需要二级指针来改变。概括来说,用函数改变一个数据需要一级指针,改变一个一级指针需要二级指针。