文章目录
指针是C语言的灵魂,也是C中最复杂的知识点,没有之一。从根本上看,指针(pointer)是一个值为内存地址的变量(或数据对象)。正如char类型变量的值是字符,int类型变量的值是整型数据,指针变量的值是地址。
1. 指针的声明、运算符和操作
声明指针变量时必须指定指针所指向变量的类型,因为不同的变量类型站用不同的存储空间,一些指针操作要求知道操作对象的大小。另外,程序必须知道储存在指定地址上的数据类型。下面是一些指针的声明实例:
int * pi; //pi是指向int类型变量的指针
float * p; //p是指向float类型变量的指针
char * n; //n是指向char类型变量的指针
类型说明符表明了指针所指向对象的类型,星号(*)表明声明的变量是一个指针。*和指针之间的空格可有可无,通常,在声明时使用空格,解引用变量时省略空格。
与指针相关的运算符有两个:地址运算符&和间接(或解引用)运算符*。&后跟一个变量时,给出该变量的地址;*后跟一个指针名或地址时,给出存储在指针指向地址上的值。
指针的操作包括:
操作 | 说明 |
---|---|
赋值 | 可以把地址赋给指针,例如,数组名,带地址运算符的变量名。但是注意地址和指针类型兼容 |
解引用 | *运算符给出指针指向地址上储存的值 |
取址 | 指针变量也有自己的地址和值,&运算符给出指针本身的地址 |
指针与整数相加 | 整数会和指针所指向类型的的大小(以字节为单位)相乘,然后把结果与初始地址相加 |
递增指针 | 递增指向数组元素的指针可以让该指针移动至数组的下一个元素 |
指针减去一个整数 | 指针必须是第1个运算对象,整数是第2个运算对象。整数会和指针所指向类型的的大小(以字节为单位)相乘,然后用初始地址减去乘积 |
递减指针 | 除递增指针之外,还可以递减指针 |
指针求差 | 通常,求差的指针分别指向同一数组的不同元素,通过计算求出两元素之间的距离。差值的单位与数组类型的单位相同 |
比较 | 使用关系运算符可以比较两个指针的值,前提是两个指针都指向相同类型的对象 |
补充:
- 不能解引用未初始化的指针,因为创建一个指针时,系统只分配了存储指针本身的内存,并未分配储存数据的内存。在使用指针之前,必须先用已分配的地址初始化它,指针的初始化用&运算符。示例:
int * pt; //未初始化的指针
*pt=5; //严重的错误
但是
int n;
int * pt = &n; //给pt赋值
*pt = 10; //给指针所指向的内存赋值
有效;
- 指针与整数相加减时,如果结果超出初始指针所指向的范围,则行为未定义;
- 如果两个指针所指向的类型不同,求差运算可能得到一个整数也可能运算错误。
2. 数组与指针
数组和指针关系密切,指针能够更有效的处理数组,数组表示法其实就是在变相地使用指针:数组名是数组首元素的地址。即如果str是一个数组,则str == &str[0];
成立,str和&str[0]都表示数组首元素地址。利用数组下标获取str[i]的值也可以写成*(str+i)。
另外,写法不同,表达的意思完全不同。例如,int * p[4];
表示指针数组,即存储指针的数组。因为方括号的优先级高于*,所以p先和[]结合,表示这是一个包含四个元素的数组,再和*结合,表示这个数组里存储的是指针变量,int表示指针所指向的值是整型的。而int (* p)[4];
表示数组指针,即指向数组的指针。因为p先和*结合,说明p是一个指针,再和[]结合,表示指针指向一个数组,再与int结合,说明数组里面的是四个整型的元素。下面的图可以帮助理解:

还有const和指针结合使用也要注意,
double rates[5] = {
88.99, 100.12, 59.45, 183.11, 340.5};
const double * pc = rates;
表示指针pc所指向的地址里面的值不能改变,但是可以改变pc所指向的地址。
double rates[5] = {
88.99, 100.12, 59.45, 183.11, 340.5};
double * const pc = rates;
表示指针所指向的地址不能改变,但是可以改变地址里面存储的值。更甚者const double * const pc = rates;
表示指针既不能更改所指向的地址,也不能更改地址里面的值。
3. 函数与指针
在函数中可以使用指针形参,可以声明数组形参。例如下面程序(程序来源于《C Primer Plus》第六版中文版第10章,书293面程序清单10.11 sum_arr2.c)处理数组:
/*数组元素之和*/
#include <stdio.h>
#define SIZE 10
int sump(int *start, int *end); //两个指针,第1个指向数组的开始,第2个指向数组的结束
int main(void)
{
int marbles[SIZE] = {
20, 10, 5, 39, 4, 16, 19, 26, 31, 20};
long answer;
answer = sump(marbles, marbles + SIZE);
printf("The total numbre of marbles is %ld\n", answer);
return 0;
}
int sump