3.2.3. Operations on basic data types

The ARM compilers perform the usual arithmetic conversions set out in relevant sections of the C and C++ standards. The following sections document additional points that should be noted with respect to arithmetic operations.

Operations on integral types

The following points apply to operations on the integral types:

• All signed integer arithmetic uses a two's complement representation.

• Bitwise operations on signed integral types follow the rules that arise naturally from two's complement representation. No sign extension takes place.

• Right shifts on signed quantities are arithmetic.

• Any quantity that specifies the amount of a shift is treated as an unsigned 8-bit value.

• Any value to be shifted is treated as a 32-bit value.

• Left shifts of more than 31 give a result of zero.

• Right shifts of more than 31 give a result of zero from a shift of an unsigned or positive signed value. They yield –1 from a shift of a negative signed value.

• The remainder on integer division has the same sign as the divisor.

• If a value of integral type is truncated to a shorter signed integral type, the result is obtained by discarding an appropriate number of most significant bits. If the original number was too large, positive or negative, for the new type, there is no guarantee that the sign of the result will be the same as the original.

• A conversion between integral types does not raise a processor exception.

• Integer overflow does not raise a processor exception.

• Integer division by zero raises a SIGFPE exception.

Operations on floating-point types

The following points apply to operations on floating-point types:

• Normal IEEE 754 rules apply.

• Rounding is to the nearest representable value by default.

• Conversion from a floating-point type to an integral type causes a floating-point exception to be raised only if the value cannot be represented in the destination type (int or long long).

• Floating-point underflow is disabled by default.

• Floating-point overflow raises a SIGFPE exception by default.

• Floating-point divide by zero raises a SIGFPE exception by default.

Pointer subtraction

The following remarks apply to all pointers in C, and to pointers other than pointers to members in C++:

• When two pointers are subtracted, the difference is obtained as if by the expression:

```((int)a - (int)b) / (int)sizeof(type pointed to)
```
• If the pointers point to objects whose size is one, two, or four bytes, the natural alignment of the object ensures that the division will be exact, provided the objects are not packed.

• For longer types, such as double and struct, the division may not be exact unless both pointers are to elements of the same array. Also, the quotient may be rounded up or down at different times. This can lead to inconsistencies.

Expression evaluation

The compiler performs the usual arithmetic conversions (promotions) set out in the appropriate C or C++ standard before evaluating an expression. The following should be noted:

• The compiler may re-order expressions involving only associative and commutative operators of equal precedence, even in the presence of parentheses. For example, a + (b – c) may be evaluated as (a + b) – c if a, b, and c are integer expressions.

• Between sequence points, the compiler may evaluate expressions in any order, regardless of parentheses. Thus the side effects of expressions between sequence points may occur in any order.

• The compiler may evaluate function arguments in any order.

Any detail of order of evaluation not prescribed by the relevant standard may vary between releases of the ARM compilers.