对于初学者来说,对指针的理解有些困难,呵呵,那么就以群中一个初学者提出的问题进行解答,希望对大家有所帮助。
说起指针,就不得不提内存,把指针与内存结合起来,才可以真正理解指针的本质。
代码就不在这里贴了,我用VC6建了一个工程,把相关的代码贴在工程中,大家可以从后面的网址中下载这个附件(http://d.1tpan.com/tp1297298259
),看看代码。
讲个概念,指针其实就是一个内存地址,指针也是一个变量,他里面存的数值就是内存地址。
我们可以简单的理解,所有我们的程序,包括程序(函数),变量都是放在内存中的,那么,所有的程序(函数),变量在内存中就有一个地址,如果大家用心可以用到函数指针,这个函数指针指的就是函数的地址。
如果我们定义一个变量,静态变量,全局变量,局部变量,不讲那么细,只概要的说,如下
int a = 10;
那么在这个变量所在的程序被运行时,变量 a 就会有一个对应的内存地址,在现在我们使用的系统中(windows,linux),因为大部分还是32位的系统,所以我们可以用一个32位的二进制数来表示地址,因为4个二进制数可能用一个16进制数来表达,所以一般我们用8个16进制数来表示内存地址,如 0x12345678。
仅以说明问题为标准,我们抛弃windows,linux系统对内存管理的不同,我们举简单的例子。
因为变量a占用的内存地址是 4 个字节,那么假设存放变量 a 的开始内存地址是 0x10000000,那么a所占的内存地址是
0x10000000
0x10000001
0x10000002
0x10000003
同时,首地址0x10000000就是变量a的地址。这块内存中的内容是值 10。
我们定义指针变量
int *p = &a;
变量p是一个指针变量,他也是一个变量,呵呵,他也要在内存中占据一定的位置,我们假设他所占的内存地址是
0x10000004
0x10000005
0x10000006
0x10000007
同时,首地址0x10000004也是变量p的地址。那么以0x10000004 开头的内存中存放的什么内容呢,就是变量a的地址值 0x10000000,
再往下类推下去,
int **q = &p;
这个我就不推了,反正知道q也是变量,他也要占据一块内存,他里面的内容是变量p的地址值0x10000004
好了,上面讲了那么多,我们试着用这种方法来解答程序中的问题。
//不能完成互换功能
void huhuan_1(int a, int b)
{
int t;
t = a;
a = b;
b = t;
return;
}
为什么这个函数不能完成a,b值的互换功能。
我们一般是用下面的方式调用的
int a1 = 3;
int b1 = 5;
huhuan_1(a1, b1);
从内存的角度来分析,假设变量a1占的内存地址是
0x10000000
0x10000001
0x10000002
0x10000003
这块内存中存放的值是数字3,
假设变量b1占的内存地址是
0x10000004
0x10000005
0x10000006
0x10000007
这块内存中存放的值是数字5,
同时我们还要知道,函数huhuan_1在调用时,系统会给函数的两个参数a,b分配临时的内存,这块内存会在函数huhuan_1调用完成后由系统回收(内存是在栈上分配的,有兴趣的可以查查)。
假设两个参数a,b分配的临时内存地址为
a的临时内存地址为:
0x20000000
0x20000001
0x20000002
0x20000003
因为我们调用时,把a1的值赋给了a,所以这块内存中的内容就是3。
同时,b的临时内存地址为
0x20000004
0x20000005
0x20000006
0x20000007
因为我们调用时,把b1的值赋给了b,所以这块内存中的内容就是5。
函数中完成了a,b内容的互换,也就是说把0x20000000至0x20000003中的内容换成了5,0x20000004 至 0x20000007中的内容换成了3。然后函数huhuan_1执行完成,a,b的内存被系统回收,此时我们再看变量a1,b1的内容被互换了吗,也就是说0x20000000 至 0x20000003的内容与0x20000004至0x20000007的内容被互换了吗,显然没有。
所以,函数huhuan_1不可能完成值的互换。
用此方法再分析函数huhuan_2
//不能完成互换功能
void huhuan_2(int * p, int * q)
{
int *t;//如果要互换p和q的值,则t必须是int *,不能是int,否则会出错
t = p;
p = q;
q = t;
}
我们用下面的方式调用
int a1 = 3;
int b1 = 5;
huhuan_2(&a1, &b1);
a1,b1分配的内存地址参考函数huhuan_1中的说明。
同函数huhuan_2在调用时,系统会给函数的两个指针参数p,q分配临时的内存,这块内存会在函数huhuan_2调用完成后由系统回收(内存是在栈上分配的,有兴趣的可以查查)。
假设两个参数p,q分配的临时内存地址为
p的临时内存地址为:
0x20000000
0x20000001
0x20000002
0x20000003
因为我们调用时,把a1的地址赋给了p,所以这块内存中的内容就是a1的地址 0x1000000。
同时,q的临时内存地址为
0x20000004
0x20000005
0x20000006
0x20000007
因为我们调用时,把b1的地址赋给了q,所以这块内存中的内容就是b1的地址 0x1000004。
函数中完成了p,q内容的互换,也就是说把0x20000000至0x20000003中的内容换成了b1的地址0x1000004,0x20000004 至 0x20000007中的内容换成了a1的地址0x1000000。然后函数huhuan_2执行完成,p,q的内存被系统回收,此时我们再看变量a1,b1的内容被互换了吗,也就是说0x20000000 至 0x20000003的内容与0x20000004至0x20000007的内容被互换了吗,显然没有。
所以,函数huhuan_2不可能完成值的互换。
用此方法再分析函数huhuan_3
//可以完成互换功能
void huhuan_3(int * p, int * q)
{
int t; //如果要互换*p和*q的值, 则t必须定义成int,不能定义成int *, 否则语法出错
t = *p; //p是int *, *p是int
*p = *q;
*q = t;
}
我们用下面的方式调用
int a1 = 3;
int b1 = 5;
huhuan_3(&a1, &b1);
a1,b1分配的内存地址参考函数huhuan_1中的说明。
同函数huhuan_1在调用时,系统会给函数的两个指针参数p,q分配临时的内存,这块内存会在函数huhuan_3调用完成后由系统回收(内存是在栈上分配的,有兴趣的可以查查)。
假设两个参数p,q分配的临时内存地址为
p的临时内存地址为:
0x20000000
0x20000001
0x20000002
0x20000003
因为我们调用时,把a1的地址赋给了p,所以这块内存中的内容就是a1的地址 0x1000000。
同时,q的临时内存地址为
0x20000004
0x20000005
0x20000006
0x20000007
因为我们调用时,把b1的地址赋给了q,所以这块内存中的内容就是b1的地址 0x1000004。
需要特别说明下,*p的意义是取p内存中的内容也就是首地址0x20000000中的内容 0x10000000,
p 是一个指针,它是一个指针变量,他的内存地址是0x20000000,
而内存地址0x20000000中放的内容是一个地址值,这个值是0x10000000,也就是变量a1的地址。
所以*p取的是地址0x10000000中的值,也就是变量a1的地址中的值,也就是3。
函数中完成了p,q所指向的地址中的值的互换,也就是说把0x10000000至0x10000003中的内容与0x10000004至0x10000007中的内容互换了。
就是说0x10000000至0x10000003中的内容变成了5,0x10000004至0x10000007中的内容变成了3.
然后函数huhuan_3执行完成,p,q的内存被系统回收,此时我们再看变量a1,b1的内容被互换了吗,也就是说0x20000000 至 0x20000003的内容与0x20000004至0x20000007的内容被互换了吗,显然完成了互换。
所以,函数huhuan_3完成了值的互换。
如果细心看完,呵呵,再仔细结合内存分析,就好理解了。
mail:sulongvc@163.com
QQ:361541630
有什么问题可以问我。
本来想弄个图出来的,因为时间晚了,所以,以后再整理吧。