ISO/IEC 9899:2011 条款6.5.6——加法操作符
6.5.6 加法操作符
语法
1、additive-expression:
multiplication-expression
additive-expression + multiplication-expression
additive-expression - multiplication-expression
约束
2、对于加法,要么操作数都应该具有算术类型,要么其中一个操作数应该是一个指向一个完整对象类型的指针,而另一个应该具有整数类型。(递增等价于加1。)
3、对于减法,应该遵守下列条款其中之一:
——两个操作数都具有算术类型;
——两个操作数都是指向兼容完整对象类型的限定的或非限定的版本;或
——左操作数是一个指向一个完整对象类型的一个指针,且右操作数具有整数类型。(递减等价于减1。)
语义
4、如果两个操组数都具有算术类型,那么通常的算术转换对这两个操作数上执行。
5、双目 + 操作符的结果是操作数的和。
6、双目 - 操作符的结果是第一个操作数减去第二个操作数的差。
7、出于对这些操作符的目的,一个指向一个对象的指针,该对象不是一个数组的元素,那么行为与指向一个长度为1的数组的第一个元素的指针相同,该对象的类型作为其元素类型。
8、当具有一个整数类型的一个表达式被加到或用一个指针去减的时候,该结果具有指针操作数类型。如果指针操作数指向一个数组对象的一个元素,并且该数组足够大,那么结果为指向从原始元素的一个元素偏移,诸如结果下标和原始数组元素的差等于整数表达式。换句话说,如果表达式是P指向一个数组对象的第i个元素,那么表达是(P) + N(等价于N + (P))与(P) - N(这里,N具有值n),分别指向数组对象的第i+n个与第i-n个元素,在它们退出时提供。此外,如果表达式P指向指向一个数组对象的最后一个元素,那么表达式(P) + 1指向越过一个数组对象的最后一个元素,并且如果表达式Q指向超过一个数组对象的最后一个元素,那么表达式(Q) - 1指向一个数组对象的最后一个元素。如果两个指针操作数与指向同一数组对象的元素的结果,或者一个超过一个数组对象最后一个元素,那么计算不应该产生一个上溢;否则,该行为是未定义的。如果该结果指向一个超过数组对象的最后一个元素,那么它不应该被用作为一个要被计算的单目 * 操作符的操作数。
9、当两个指针相减时,两个指针都应该指向同一个数组对象的元素,或者超过数组对象最后一个元素;结果是两个数组元素的下标的差。结果的大小是实现定义的,并且其类型(一个带符号整数类型)是定义在<stddef.h>头文件中的ptrdiff_t。如果结果不能用该类型的一个对象来表示,那么行为是未定义的。换句话说,如果表达式P和Q分别指向一个数组对象的第i个以及第j个元素,那么表达式(P) - (Q)具有值i-j所提供的值适应于类型ptrdiff_t的一个对象。此外,如果表达式P要么指向一个数组对象的一个元素,要么指向超过一个数组对象的最后一个元素,并且表达式Q指向同一数组对象的最后一个元素,那么表达式 ((Q) + 1) - (P)) 具有与((Q) - P) + 1)和-((P) - ((Q) + 1))相同的值,如果表达式P指向一个超过一个数组对象最后一个元素,那么具有值零,即便表达式(Q) + 1并不指向一个数组对象的一个元素。[注:实现指针算术的另一种方法是先将指针转换为字符指针;在这种模式下,整数表达式与被转换的指针相加,或被转换的指针减去该整数表达式,先乘以原始被指的对象的大小,然后结果指针被转换回原始类型。对于指针减法,在字符指针之间的差类似于乘以原始所指的对象的大小。当用这种视角去看时,一个实现不仅需要提供一个额外的字节(这可能在程序中跌交另一个对象),恰好在对象末尾之后,为了满足“一个超过最后一个元素”的要求。]
10、例 指针算术用指向可变长度数组类型是良好定义的。
{ int n = 4, m = 3 int a[n][m]; int (*p)[m] = a; // p == &a[0] p += 1; // p == &a[1] (*p)[2] = 99; // a[1][2] == 99 n = p - a; // n == 1 }
11、如果上述例子中的数组a被声明为已知常量大小的一个数组,并且指针p被声明为指向一个相同已知常量大小的数组(指向a),结果将是相同的。