本文内容摘自《C和指针》
指针的运算包括算术运算和关系运算。只有指向数组元素的指针可以进行指针的运算。
算术运算
指针的算术运算仅限于2种形式。
第一种形式:指针 ± 整数
标准定义这种形式只能用于指向数组中某个元素的指针。这类表达式的结果类型也是指针。
对一个指针加1会使它指向数组中下一个元素,加5使它右移5个元素的位置。对一个指针减3使它向左移动3个元素的位置。对某一类型的指针,指针加1是指指针的值增加1个该类型的大小,而不是1个字节。整数在执行加法运算前始终会根据数组元素类型的大小进行调整。例如:
- 在某台机器上float占据4个字节,float型指针加3时,指针的值会增加12个字节。
- 而char型指针加3时,则指针的值只增加3个字节。
一个指针减去一个整数后,如果结果指针指向数组第一个元素之前,那么它是非法的。
一个指针增加一个整数后,如果结果指针指向数组最后一个元素之后,仍是合法的,但不允许对其执行间接访问操作。
第二种形式:指针 - 指针
只有当2个指针都指向同一个数组中的元素,才允许从一个指针减去另一个指针。否则结果是未定义的。
两个指针相减的结果的类型是ptrdiff_t,是标准库中定义的一个与机器相关的数据类型,它是一种有符号整数类型。减法运算的值是两个指针在内存中的距离,以数组元素的长度为单位,而不是以字节为单位,这使指针的运算结果与数据类型无关。减法运算的结果允许是负值。例如p2-p1的值为5,则p1-p2的值则为-5。
关系运算
同样的,关系运算的前提是2个指针都指向同一个数组中的元素。
标准允许指向数组元素的指针与指向数组最后一个元素后面的内存位置的指针进行比较。
标准不允许指向数组元素的指针与指向数组第一个元素之前的那个内存为止的指针进行比较。
例如,利用循环清除一个数组中的元素:
#define N_VALUES 5
float values[N_VALUES];
float *p;
//循环1
for(p = &values[0]; p < &values[N_VALUES]; )
{
*p++ = 0;
}
//循环2
for(p = &values[N_VALUES]; p > &values[0]; )
{
*--p = 0;
}
//循环3
for(p = &values[N_VALUES - 1]; p >= &values[0]; p--)
{
*p = 0;
}
对于以上3个循环,循环1和循环2能够完成数组清零。循环3则存在问题。
循环1:最后一次比较,p指向values[N_VALUE]位置,循环终止,并未对p执行间接访问操作,因此是安全的。
循环2:最后一次比较,p指向values[0],循环终止。
循环3:最后一次比较,p指向values[0]前面的内存位置,此时p指针与values[0]指针做比较,结果是未定义的。
附:*p++和*(p++)是等价的,++运算符的优先级高于*运算符。