1.指针定义
指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑储存器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元。
2.指针使用方法
2.1指针与数组
首先,一个很重要的知识点即数组名是数组首元素的地址。也就是说,如果sz是一个数组,则:
sz==&sz[0];//成立
sz和&sz[0]都表示数组首元素的地址(&是地址运算符)。两者都是常量,在程序运行过程中不会改变。
- 指针的值是它所指向对象的地址
- 在指针前使用*运算符可以得到该指针所指向对象的值 *在指针运算中代表的意思是解引用,而不是
乘以。 - 指针+n,指针的值跳到它所指向类型的大小(sizeof typename 以字节为单位)×n 在C中,指针+1指的是增加一个存储单元。对数组而言,这意味着+1后的地址是下一个元素的地址,而不是下一个字节的地址。这就是为什么要声明指针所指向对象类型的原因之一。
//指针地址示例
#include<stdio.h>
#define SIZE 4
int main()
{
short dates[SIZE];
short *pti;
short index;
double bills[SIZE];
double *ptf;
pti = dates; //把数组地址赋给指针
ptf = bills;
printf("%23s %15s\n","short","double");
for(index = 0; index < SIZE; index++)
printf("printers + %d: %10p %10p\n",index,pti + index, ptf + index);
return 0;
}
//输出示例 十六进制
short double
printers + 0: 000000000062FE30 000000000062FE10
printers + 1: 000000000062FE32 000000000062FE18
printers + 2: 000000000062FE34 000000000062FE20
printers + 3: 000000000062FE36 000000000062FE28
//short类型占用2字节,所以30--> 32--> 34--> 36
//double类型占用8字节,所以10--> 18--> 20 -->28
2.1.1与一维数组:
2.1.2与多维数组
int zip[4][2]; //内含int数组的数组
- 数组名zip是该数组的首元素的地址。zip的值和&zip[0]的值相同。而zip[0]本身是一个含有2个int的数组,所以zip[0]的值和它的首元素(一个整数)的地址(即&zip[0][0]的值)相同。简而言之,zip[0]值一个占用一个int大小对象的地址,而zip是一个占用两个int大小对象的地址。由于这个整数和内含两个整数的数组都开始于同一地址,所以zip和zip[0]的值相同。
- 给指针或地址+1,其值会增加对应类型大小的值。在这方面,zip和zip[0]不同,因为zip指向的对象占用了两个int大小的内存单位,而zip[0]指向的对象只占用了一个大小的内存单位。因此,zip+1和zip[0]+1的值不同。
- 解引用一个指针(在指针前用*运算符)或在数组名后使用带下标的[]运算符,得到引用对象代表的值。因为zip[0]是该数组首元素(zip[0][0])的地址,所以*(zip[0])表示储存在zip[0][0]上的值(即一个int类型的值)。与此类似,*zip代表该数组首元素(zip[0])的值,但zip[0]本身是一个int类型值(zip[0][0])的地址,所以*zip就是&zip[0][0]。对两个表达式应用解引用运算符表明,**zip与 *&zip[0][0]等价,这相当于&zip[0][0],即一个int类型的值。简而言之,zip是地址的地址,必须解引用两次才能获得原始值。地址的地址或者指针的指针就是双重间接的例子
2.1.3特别的还有,指针与字符数组。
实际上,字符串的绝大多数操作都是通过指针完成,因为字符串常量是一个字符数组。例如:
str = "I am a string";
将把一个指向该字符串的指针赋值给str。该过程没有进行字符串的复制,而只是涉及到指针的操作。
C语言没有提供将整个字符串作为一个整体进行处理的运算符。下面两个定义有很大的差别:
char a[] = "cool boy"; //定义一个数组
char *b = "cool boy"; //定义一个指针
上述声明中a是一个仅仅足以存放初始化字符串以及空字符‘\0’的一维数组。数组中的单个字符可以进行修改,但a始终指向同一个存储位置。另一方面,b是一个指针,其初始值指向一个字符串常量,之后它可以被修改以指向其他地址,但如果试图修改字符串内容,结果是未定义的。
2.2.指针与函数
2.2.1函数指针
首先,举一个函数指针的例子。假设有一个指向int类型变量的指针,该指针储存着这个int类型变量储存在内存位置的地址。同样函数也有地址,因为函数的机器语言实现由载入内存的代码组成。指向函数的指针中储存着函数代码的起始处的地址。
其次,声明一个函数指针所指向的数据类型。声明一个函数指针是,必须声明指针指向的函数类型。为了指明函数类型,要指明函数签名,即函数的返回类型和形参类型。例如:
void (*pr) (char *);
pr是一个指向函数的指针,(*pr)是一个参数列表为(char *)、返回类型为void的函数。
!注意:如果
void *pt (char *);
则表示pt是一个返回字符指针的函数。
2.2.2指针作函数的形参