C提供了6种基本的指针操作
示例代码:
#include <stdio.h>
int main(void)
{
int arr[5] = {1, 2, 3, 4, 5};
int * p1, *p2, *p3;
p1 = arr; // 把一个地址赋给指针
p2 = &arr[2]; // 把一个地址赋给指针
printf("指针指向的地址,指针指向地址中存储的内容,指针本身的地址:\n");
printf("p1 = %p, *p1 = %d, &p1 = %p\n", p1, *p1, &p1);
// 指针加法
printf("\n");
p3 = p1 + 4;
printf("增加指针值:\n");
printf("p1 + 4 = %p, *(p1 + 4) = %d\n", p3, *p3);
// 递增指针
printf("\n");
p1++;
printf("p1递增后的值:\n");
printf("p1 = %p, *p1 = %d, &p1 = %p\n", p1, *p1, &p1);
// 递减指针
printf("\n");
p2--;
printf("p2递减后的值:\n");
printf("p2 = %p, *p2 = %d, &p2 = %p\n", p2, *p2, &p2);
// p1和p2恢复为初始值
printf("\n");
--p1;
++p2;
printf("恢复为初始值后:\n");
printf("p1 = %p, p2 = %p\n", p1, p2);
// 一个指针减去另一个指针
printf("\n");
printf("指针2减指针1:\n");
printf("p2 = %p, p1 = %p, p2 - p1 = %p\n", p2, p1, p2 - p1);
// 一个指针减去一个整数
printf("\n");
printf("指针3减一个整数:\n");
printf("p3 = %p, p3 - 2 = %p\n", p3, p3 - 2);
return 0;
}
运行结果:
可以对指针变量执行的基本操作:
1)赋值:可以把一个地址赋给指针
通常使用数组名或地址运算符&进行地址赋值
2)求值或取值:使用预算符*可取出指针指向地址中存储的数值
3)取指针地址:指针变量同其他变量一样具有地址和数值,使用运算符&可以得到存储指针本身的地址
4)将一个整数加给指针:可以使用+运算符把一个整数加给指针,或者把一个指针加给一个整数
整数会和指针所指类型的字节数相乘,所得结果加到初始地址上
如果相加的结果超出了初始指针所指向的数组的范围,则会出现不确定结果
5)增加指针的值:通过加法或增量运算符
对指向某数组元素的指针做增量运算,会让指针指向该数组的下一个元素
6)从指针中减去一个数:可以使用-运算符从一个指针中减去一个整数,与将一个整数加给指针类似
7)减小指针的值:与增加指针的值类似
8)求差值:求出两个指针之间的差值
通常对分别指向同一数组内两个元素的指针求差值,获得元素之间的距离
差值的单位是相应类型的大小(如2个int的大小)
9)比较:使用关系运算符比较两个指针的值,前提是两个指针具有相同的类型
两种形式的减法:可以用一个指针减掉另一个指针得到一个整数;也可以从一个指针中减去一个整数得到一个指针
计算机不检查指针是否仍然指向某个数组元素;C保证指向数组元素的指针和指向数组后的第一个地址的指针都是有效的;如果指针在进行了增量或减量运算后超出了这个范围,后果将是未知的
可以对指向一个数组元素的指针进行取值运算,但不能对指向数组后的第一个地址的指针进行取值运算,尽管这样的指针是合法的
不要对未初始化的指针取值:
int *p; // 一个未初始化的指针
*p = 5; // 一个危害极大的赋值
// 把数值5存储在p所指向的地址
// 由于p没有被初始化,因此其值是随机的,不知道数值5会被存储到什么位置
// 这个位置也许对系统危害不大
// 但是也许会覆盖已有的程序数据或代码,甚至导致程序崩溃
当创建一个指针时,系统只分配了用于存储指针本身的内存空间,并不分配用于存储数据的内存空间
因此在使用指针之前,必须给其赋予一个已分配的内存地址,例如可以把一个已存在的变量地址赋给指针,或者使用函数malloc()函数分配内存
使用指针时一定要小心
指针的2个基本功能:
1)指针最基本的功能在于同函数交换信息;如果需要让被调函数修改调用函数中的变量,就必须使用指针
2)指针的另一个基本功能是用于处理数组的函数中