(如有不合理的地方,欢迎纠正)
一级指针的使用
在讨论指针的使用前,先重温一下函数的概念。在C语言中可以采用分组方式管理程序中的语句,我们把每个分组叫做一个函数。函数调用语句可以在程序执行过程中产生函数调用关系,但是一般情况下,一个函数不能使用其他函数的存储区如果函数被分配了多段时间则不同段时间内使用不同的存储区。
如果要实现跨函数使用存储区,这时候就比需要用到指针。
例一:
<span style="background-color: rgb(255, 255, 255);">#include <stdio.h>
void swap(int num, int num1)
{
int tmp = num;
num = num1;
num1 = tmp;
}
void swap2(int *num, int* num1)
{
int tmp = *num;
*num = *num1;
*num1 = *tmp;
}
int main()
{
int num = 3;
int num1 = 7;
printf("num = %d, num1 = %d\n"num, num1);
swap(num, num1);
printf("num = %d, num1 = %d\n"num, num1);
swap2(&num, &num1);
printf("num = %d, num1 = %d\n"num, num1);
return 0;
}
</span>
在上述例子中,当调用swap()函数后,num和num1的值并没有改变,原因是因为函数所提供的参数是形式参数,它的传递方式是值传递,被调用函数所赋值的只是参数的值。当调用swap2的函数后,由于传递过去是一个地址,也就是main()里的num 和 num1的地址,所以在swap2()里是直接修改main()函数里num和num1的地址的数据。
二级指针的使用
二级指针是用来记录一级指针的地址,二级指针本身代表它自己存储区或里面的数据。
例 二:
<span style="background-color: rgb(255, 255, 255);">#include <stdio.h>
int main()
{
int num = 0;
int *p_num = #
int **pp_num = &p_num;
num = &pp_num;
<span style="white-space:pre"> </span>***(int***)num = 10;
printf("num == %d\n", num);
return 0;
}</span><span style="background-color: rgb(204, 204, 204);">
</span>
在例二中,p_num是一个一级指针,存储的是num的地址,假设num的地址是0xbfa5b018,那么p_num存储的值用16进制表示就是0xbfa5b018。
*p_num的意思是把p_num的值取出来,当一个存储区使用。那么*p_num和num所代表的都是编号为0xbfa5b018的存储区,修改*p_num的值,也就是修改num的值。
pp_num是一个二级指针,他本身存储的值等于p_num的地址,修改*pp_num的值等同于修改p_num的值,对修改**pp_num的值,也就是修改*p_num和修改num的值。
在32位平台下,所有指针变量都是占4个字节的大小。所以理论上整型变量能当作任何基本数据类型的指针使用,因为它的存储区足够记录下任意一个的地址,只需要在使用的时候通过强制类型转换,就能得到我们想要的效果。
就如例二中,num是一个整型的数据类型,大小位4个字节,所以把pp_num的地址当作一个整数赋值给num本身是没有任何问题的,通过强制类型转换,把num转为一个三级指针(三级指针存储的是二级指针的地址编号),然后再通过*(对其解引用)就可以得到pp_num的值,关系如下
(int***)num == &pp_num;
*(int***)num == pp_num;
**(int***)num == *pp_num == p_num;
***(int***)num== **pp_num == *p_num == num == 10;
指针变量存储的是地址,地址就是系统给内存的一个编号,这个编号是一个整数,通过*可以对指针变量存储的整数当作一个存储区使用。所以指针变量也就是一个利用4个字节(32位平台)存储一个整数的变量,但我们要保证的是,这个整数被当作一个地址使用的时候,这个地址必须是个有效的地址。只要能清楚的了解到这点,就能减少学习指针时候晕针的情况。