指针变量可以进行赋值运算、加减算术运算和关系运算。下图描述了C语言指针的赋值和加减算术运算。

赋值运算
指针变量可以把其值赋值给指向相同类型的另一个指针变量。如指针变量A赋值给指针变量B后,指针变量A和B会指向同一个内存地址。
指针变量赋值代码段:
int a,*p1,*p2;
p1 = &a;
p2 = p1;
变量和指针变量可以在同一行语句中声明,指针变量需要在名称前面加“*”。指针变量p1的值为变量a的内存地址,p2 = p1赋值语句将p1的值赋值给p2,此时p1和p2都指向变量a的内存地址。
加减算术运算
指针变量存储的是其它变量或程序对象的内存地址,内存地址实际上是一个整数。下面的代码段输出了变量a的内存地址。
float a=3.1f;
printf("变量x的内存地址=%d\n",&a);
输出结果:

既然内存地址是一个整数,指针变量存储的是内存地址,指针变量自然就支持整数的算术元素和关系运算。指针变量使用的算术运算符主要是加法、减法、自增和自减运算符。
例【1】指针变量的加减算术运算
程序清单 sample.c
#include <stdio.h>
void main()
{
int a=30,b=20;
int* pa = &a;
printf("变量a的内存地址=%d\n",&a);
printf("变量b的内存地址=%d\n",&b);
printf("*pa=%d\n",*pa);
// 指针变量的值做加3运算
pa=pa-3;
// 输出指针变量指向内存地址的数据
printf("*pa=%d",*pa);
}
例7-3演示了指针变量的加法运算,语句pa=pa-3将指针变量pa存储的内存地址减去12个字节,再赋值给pa。赋值给pa是赋值给pa保存的内存地址,而不是pa本身的内存地址。有同学可能会问,运算是减去3,怎么会是减去12个字节呢?指针变量的算术运算单位不是字节,而是指针指向的数据类型所占用的存储空间,pa指针是int类型的指针,int类型在32位操作系统中占4个字节。
pa-3的目的是让指针变量pa指向变量b的内存地址,在《理解C语言的指针》一节谈到了C编译器会为变量a和b分配连续的存储空间,由于字节对齐的缘故,实际分配到变量a和b的存储空间为12个字节,而不是4个字节,但指针的运算是按照数据数据类型占用的存储空间来计算的。
例1的输出结果:

从输出结果可以看出,变量a和变量b的内存地址相差12个字节,变量a的内存地址减去12个字节正好是变量b的内存地址,因此最后一条printf语句正确输出了变量b的值。
试想一下,如果对指针变量做pa=pa-2运算,pa不会指向变量b的内存地址,而是指向一个我们无法预知的内存地址,最后一条printf语句会输出错误的数值。
指针变量还支持关系运算符,使用关系运算符,可以判断两个指针变量内存地址的关系。
例【2】指针变量的关系运算
程序清单 sample.c
#include<stdio.h>
void main()
{
int *ptr1,*ptr2;
int value = 10;
// 变量value的地址赋值给ptr1
ptr1 = &value;
// value做加1操作
value = value+1;
// 变量value的地址赋值给ptr2
ptr2 = &value;
// 判断两个指针变量的值是否相等
if( ptr1 == ptr2 )
{
printf("\n两个指针指向同一个地址\n");
}
else
{
printf("\n两个指针指向不同的地址\n");
}
}
例2演示了指针变量的关系运算,指针变量ptr1和ptr2分别被赋值为变量value的内存地址,然后判断两个指针的值是否相等,由于ptr1和ptr2都指向变量value的内存地址,因此ptr1的值和ptr2的值相等。