有8种不同的操作。指针的转换说明为%p。
1、赋值
把地址赋给指针。例如用数组名、带地址运算符(&)的变量名、另一个指针进行赋值。
int * p1 = &n;
int *p2 = p1;
int ar[3];
int p3 = ar;
注意:地址上的数据类型应该与指针类型相同。例如,不能把double类型的地址赋给指向int类型的指针(C99/C11已强制不允许这样做)。
2、解引用*
*运算符给出指针指向地址上储存的值。
int n = 3,m = 2;
int * p1 = &n; //声明指向int类型变量n的指针p1
m = *p1 // 解引用p1,并将其赋给m;m的值为3
注意:
千万不要解引用未初始化的指针。例如:
int * pt;//未初始化的指针
*pt = 5;//严重错误
第二行意思是把5存储在pt指向的位置。但是pt未初始化,其值是个随机值,所以不知道5会存储在何处。这可能不会出什么错,也可能会擦写数据或代码,或者导致程序崩溃。
创建一个指针,系统只分配了储存指针本身的内存,并未分配储存数据的内存。因此,在使用指针前,必须先用已分配的地址初始化它。无论如何,使用指针时一定要注意,不要使用未初始化的指针。
3、取地址&
与所有变量一样,指针变量也有自己的地址和值。对指针而言,&运算符给出指针本身的地址。
取地址&与解引用*是一对互逆操作。
4、指针与整数相加
可以使用+运算符把指针与整数相加,或整数与指针相加。
整数会先和指针所指类型的大小(以字节为单位)相乘,然后把结果与初始地址相加。
假设int变量n的地址为0x7fff5fbff8d0,指针ptr1指向n,int大小为4个字节。
int * ptr2 = ptr1 + 2;
ptr2 = (2*4)+0x7fff5fbff8d0 = 0x7fff5fbff8d8。
注意:如果相加的结果超出了初始指针指向的数组范围,计算结果是未定义的。除非,正好超出数组末尾一个位置,C保证该指针有效。
5、递增指针
递增指向数组元素的指针可以让该指针移动至数组的下一个元素。
注意:发生变化的是指针存储的值(即指针指向的地址发生变化),指针本身的地址不发生变化。
6、指针减去一个整数
可以使用-运算符从指针中减去一个整数。指针必须是第一个运算对象,整数是第二个运算对象。计算结果仍然是个指针。
如果相减的结果超出初始指针指向数组的范围,计算结果是未定义的。除非正好超出数组末尾第一个位置, C保证该指针有效。
7、递减指针
与递增指针类似。
注意:在递增或递减指针时,编译器不会检查指针是否仍指向数组元素。C只保证指向数组任意元素的指针和指向数组后面第一位置的指针有效。但是如果递增或递减一个指针后超出了这个范围,则是未定义的。
8、指针求差
可以计算两个指针的差值。通常,求差的两个指针分别指向同一个数组的不同元素,通过计算求出两个元素之间的距离。
计算的结果是个整数。差值的单位与数组类型的单位相同,例如,两个指向int的指针求差的结果是2,意思是这两个指针所指的两个元素相隔2个int,而不是2字节。
指针的检法有两种:(1)指针减去一个整数,结果仍是一个指针(2)两个指针相减,结果是个有单位的整数,单位是指针指向元素类型的大小。
9、比较
使用关系运算符可以比较两个指针的值。前提是两个指针都指向相同类型的对象。