摘要:总结了指针的本质,*的意义,以及传值调用和传址调用的根本区别,利用两个例程加深了理解。
一、指针的本质
指针的本质也是一个变量,只是它里面存放的是一个内存的地址,指针也是需要占用内存空间的,按照平台不同,32位指针变量占四个字节,64位的话一般是8个字节,不同类型的指针变量都是这样。这是因为,我们指针既然是存放的内存的地址,那么理论上我们可以指向系统当中的任意一个内存,既然要做到这样,就要能够访问系统地址空间那么大的内存,所以32位系统是4个字节,无论是char*还是double*的指针变量,都占用4个字节。
二、*的意义
在指针声明的时候,*表示声明的变量为指针,在使用的时候*表示取指针指向的内存地址中的值。
#类似一把钥匙,通过这把钥匙可以打开内存这个房间,取走里面的内容。
下面这个例子可以解释上面的总结:
<span style="font-size:18px;">test.c
#include<stdio.h>
int main(void)
{
int i;
int* pI;
char* pC;
double* pD;
pI=&i;
printf("%0x %0d %d%0x,%d,%d,%d\n",&i,*pI,i,&pI,sizeof(int*),sizeof(char*),sizeof(double*));
*pI=10;
printf("%0x %0x %d%0x,%d,%d,%d\n",&i,*pI,i,&pI,sizeof(int*),sizeof(char*),sizeof(double*));
return 0;
}
输出结果如下:
#bf85eadc 13623284 13623284 bf85ead8,4,4,4
#bf85eadc a 10 bf85ead8,4,4,4</span>
可以看到,无论是什么类型的指针变量都是占用四个字节,*pI和i是同一个值,因为pI指向了i的地址,对其*操作自后就是取那个内存里面的值,所以是一样的,对pI取地址可以得到指针的地址,指针也是一个变量,也是需要占用内存的,占用四个字节的大小。
三、传值调用与传址调用
1.指针是变量,因此可以声明指针参数,例如void fun(int* a,int* b)
2.当一个函数体内部需要改变实参的值,则需要使用指针参数
3.函数调用时,实参的值将复制到形参
4.指针适用于复杂数据类型作为参数的函数中
上面的总结是什么意思呢?第一个很容易理解,将指针变量作为函数的参数,在使用的时候我们可以这样fun(&I,&j);这样其实就完成了一次传地址调用,我们可以在该函数内部完成I,j实参的值的修改,这样就是第二点的总结。第三个,函数调用,实参的值复制给了形参,待会儿举个例子说明,最后指针作为复杂数据类型的参数,是因为它的传地址特性,我们不需要将复杂的实参拷贝给形参,能够大大提升效率。
例子如下:
test2.c
#include<stdio.h>
void fun1(int a,int b)
{
int i;
i=a;
a=b;
b=i;
}
void fun2(int* a,int*b)
{
int i;
i=*a;
*a=*b;
*b=i;
}
int main(void)
{
int i,j,m,n;
i=1;
j=2;
m=1;
n=2;
fun1(i,j);
fun2(&m,&n);
printf("%d %d\n",i,j);
printf("%d %d\n",m,n);
return 0;
}
输出结果如下:
#1 2
#2 1
输出结果我们可以看到,利用传值调用时没有交换两个变量的值,但是利用传地址调用就可以,原因就是我们上面总结的。那为什么在处理复杂参数的时候,我们要传地址调用呢,假如我们一个程序里面定义了很多的结构体,结构体里面有数组,很多字符串,如果传值调用,需要拷贝到形参,而传地址只需要拷贝几个指针的大小,效率相差了很多倍。
这篇帖子就总结到这里,如有不正确的地方还请指出,大家共同进步!