The additive operators perform addition (+) and subtraction (–).
additive-expression :
multiplicative-expression
additive-expression + multiplicative-expression additive-expression – multiplicative-expression
Note:
Although the syntax for additive-expression includes multiplicative-expression, this does not imply that expressions using multiplication are required. See the syntax in Appendix A for multiplicative-expression, cast-expression, and unary-expression.
The operands can be integral or floating values. Some additive operations can also be performed on pointer values, as outlined under the discussion of each operator.
The additive operators perform the usual arithmetic conversions on integral and floating operands. The type of the result is the type of the operands after conversion. Since the conversions performed by the additive operators do not provide for overflow or underflow conditions, information may be lost if the result of an additive operation cannot be represented in the type of the operands after conversion.
The addition operator (+) causes its two operands to be added. Both operands can be either integral or floating types, or one operand can be a pointer and the other an integer.
When an integer is added to a pointer, the integer value (i) is converted by multiplying it by the size of the value that the pointer addresses. After conversion, the integer value represents i memory positions, where each position has the length specified by the pointer type. When the converted integer value is added to the pointer value, the result is a new pointer value representing the address i positions from the original address. The new pointer value addresses a value of the same type as the original pointer value and therefore is the same as array indexing (see “One-Dimensional Arrays” and “Multidimensional Arrays”). If the sum pointer points outside the array, except at the first location beyond the high end, the result is undefined. See “Pointer Arithmetic” later in this section for more information.
The subtraction operator (–) subtracts the second operand from the first. Both operands can be either integral or floating types, or one operand can be a pointer and the other an integer.
When two pointers are subtracted, the difference is converted to a signed integral value by dividing the difference by the size of a value of the type that the pointers address. The size of the integral value is defined by the type ptrdiff_t in the standard include file STDDEF.H. The result represents the number of memory positions of that type between the two addresses. The result is only guaranteed to be meaningful for two elements of the same array, as discussed in “Pointer Arithmetic” later in this section.
When an integer value is subtracted from a pointer value, the subtraction operator converts the integer value (i) by multiplying it by the size of the value that the pointer addresses. After conversion, the integer value represents i memory positions, where each position has the length specified by the pointer type. When the converted integer value is subtracted from the pointer value, the result is the memory address i positions before the original address. The new pointer points to a value of the type addressed by the original pointer value.
The following examples, which illustrate the addition and subtraction operators, use these declarations:
int i = 4, j;
float x[10];
float *px;
These statements are equivalent:
px = &x[4 + i];
px = &x[4] + i;
The value of i is multiplied by the length of a float and added to &x[4]. The resulting pointer value is the address of x[8].
j = &x[i] - &x[i-2];
In this example, the address of the third element of x (given by x[i–2] ) is subtracted from the address of the fifth element of x (given by x[i] ). The difference is divided by the length of a float; the result is the integer value 2.
Additive operations involving a pointer and an integer give meaningful results only if the pointer operand addresses an array member and the integer value produces an offset within the bounds of the same array. When the integer value is converted to an address offset, the compiler assumes that only memory positions of the same size lie between the original address and the address plus the offset.
This assumption is valid for array members. By definition, an array is a series of values of the same type; its elements reside in contiguous memory locations. However, storage for any types except array elements is not guaranteed to be filled by the same type of identifiers. That is, blanks may appear between memory positions, even positions of the same type. Therefore, the results of adding to or subtracting from the addresses of any values but array elements are undefined.
Similarly, when two pointer values are subtracted, the conversion assumes that only values of the same type, with no blanks, lie between the addresses given by the operands.
On machines with segmented architecture (such as the 8086/8088), additive operations between pointer and integer values may not be valid in some cases. For example, an operation may result in an address that is outside the bounds of an array. See the reference information on these processors or reference books on segmented architecture for more information.
Note:
The results of pointer subtraction when both operands are pointers to short may overflow the intermediate result. To avoid this, cast the pointers to pointers to long. For subtraction of __huge operands, cast the difference to unsigned long to get the correct result.