1、指针和指针变量:
指针正如其名称一样,指向了内存中的某个地址。在程序中,我们可以声明一个指针变量来存储另一个变量的内存地址,我们称之为“指针Ptr指向XX变量”。
1 //例: 2 int a = 5; 3 4 int *p, *q; p = &a; // int *p = &a; 5 6 //在这里int *p;中的*仅仅表示p为指针变量。 7 8 printf("地址 = %d ",&a); 9 10 printf("地址= %d ",&*p); 11 12 printf("地址= %d ",p); 13 14 printf("地址= %d ",&p);
输出语句中的 &a、&*p、p 的值是一样的(都为变量a的内存地址值),最后一个&p为指针变量p自己的内存地址,和其他变量地址没有关系。
代码说明:先声明并初始化了一个变量a,再声明了一个指针变量p,然后把变量a在内存中的地址赋给了指针变量p。后面引用时(不是声明时)p为指针变量,*p为指针当前所指向的对象,那么*p为5(对象),p为变量a的内存地址; &*p和&a的地址是同一个;而&p是指针变量p自己的内存地址,和其他变量地址没有关系。
注: 如上例中:声明了两个指针变量p和q,那么可以写代码:
q = p;或者q = &*p; 不可以写成q = *p;因为q是用来存储变量地址的,而*p是指针当前所指向的对象(a的值5)。
2、声明指针变量:
在使用指针指向某个变量之前,必须先声明指针变量,其声明形式:
数据类型 *指针(变量)名称; 例:int *p;
说明:
- 数据类型应与指针指向的变量类型保持一致;
- 指针变量的命名与普通变量命名相同;
- 声明指针变量时要在指针变量名称之前加“*”;
- 其含义应该是:数据类型* 指针(变量)名称; //声明指针(变量)是某数据类型的指针类型;
例如:int *p; char *ch; float *f; double *d;
示例:
1 int i = 1, j = 2, *p, *q; //声明指针及其它变量 2 3 p = &i; //指针P指向变量 4 5 q = p; //指针q也指向指针P指向的地址
可以通过间接寻址符(*)得到指针指向的内容,然后对指针指向内容进行赋值操作,直接更改指针指向的变量的内容;例如:
2 *p = 5; //指针p指向的内容(变量i)的值此时已更改为5 3 *q = *p; //将指针p指向的内容赋值给指针q指向的变量中; 4 q = p; //指针p指向的地址赋值给指针q,也就是指针q与指针p指向相同的(变量)地址。
对于暂时无需使用的指针可置NULL值挂起;例如:
1 p = NULL; //指针挂起
3、指向数组的指针:
- 数组存储在一块连续内存单元中;数组名称就是这块连续内存单元的首地址;如下例:
1 int a[10], *ptr; 2 ptr = &a[0]; //或者:ptr = a;
注释:a和&a[0]是同一个地址。
- 第(i+1)个数组元素的地址可表示为&a[i]或者a+i;或者a+=i;
注:i为脚标号,a为数组名也代表了整个数组的内存地址和数组中第一个元素的内存地址;(数组中第一个元素的内存地址代表整个数组的内存地址)。
- 可通过以下方式让指针指向数组:
1 int a[10], *ptr; 2 ptr = &a[0]; //或者:ptr = a;
- 指针变量可以指向数组中的某一个元素;如:
1 ptr = a; 2 ptr += 4; //ptr += 4;为数组中第4号角标元素的内存地址(第5个元素的内存地址)。
4、指针的算术运算:
指针的算术运算,等同于指针指向一段连续的内存空间,并让指针前后移动访问数据。(可以设想为游标卡尺,度量指针的左右移动)涉及到的运算符:++、--、+=、-=。
5、指针的关系运算:
可以通过比较两个指针变量的地址是否相等,来进行比较判断。涉及到的运算符:==、!=、>、>=、<、<=。
6、返回指针的函数
指针也是C语言中的一种数据类型,因此一个函数的返回值肯定可以是指针类型的
返回指针的函数的一般形式为:类型名 * 函数名(参数列表)
7、指向函数的指针
1)为什么指针可以指向一个函数?
函数作为一段程序,在内存中也要占据部分存储空间,它也有一个起始地址,即函数的入口地址。函数有自己的地址,那就好办了,我们的指针变量就是用来存储地址的。因此,可以利用一个指针指向一个函数。其中,函数名就代表着函数的地址。
2)指向函数的指针的定义
定义的一般形式:函数的返回值类型 (*指针变量名)(形参1, 形参2, ...);
3)使用注意
由于这类指针变量存储的是一个函数的入口地址,所以对它们作加减运算(比如p++)是无意义的
指向函数的指针变量主要有两个用途:
- 调用函数
- 将函数作为参数在函数间传递