Question

Possible Duplicate:
C integer overflow behaviour when assigning to larger-width integers

I haven't found a clear answer on this in my googling. Say you have two expressions:

int16_t a16 = 100;
int16_t b16 = 2000;
int16_t result16 = (a16 * b16) / a16;

int8_t a8 = 100;
int8_t b8 = 20;
int8_t result8 = (a8* b8) / a8;

When evaluation the expressions (a16 * b16) / a16 and (a8 * b8) / a8, are they always promoted to int during the evaluation and then the final result is converted back to the desired type (int16_t or int8_t) just before the assignment, or is this integer promotion entirely optional? Is integer promotion while evaluating an integer expression always done, or is it just simply allowed?

If it's always done, then I can expect the two operations to not overflow (assuming int is 32-bits). If it's only allowed to be done (and not required), then the operations may overflow. I'd like to know the behavior better.

Was it helpful?

Solution

int16_t result16 = (a16 * b16) / a16;
int8_t result8 = (a8* b8) / a8;

These declarations are the same as:

int16_t result16 = (int16_t) ((int) a16 * (int) b16) / (int) a16);
int8_t result8 = (int8_t) ((int) a8 * (int) b8) / (int) a8);

The integer promotions are required by a conforming implementation. Some embedded compilers by default do not perform integer promotions to enhance code density (example: MPLAB C18 compiler) but these compilers usually also have an ANSI mode to be conforming.

Now for C the behavior is described in terms of an abstract machine in which the issues of optimization are irrelevant. If the compiler can achieve the same observable behavior for the program without performing an integer promotion, it is free not to do it.

Assuming your int is 32-bit, you are right, this expression: (a16 * b16) / a16 cannot overflow.

OTHER TIPS

First, we have integer promotions, 6.3.1.1/2. Footnote 58 says:

The integer promotions are applied only: as part of the usual arithmetic conversions, to certain argument expressions, to the operands of the unary +, -, and ~ operators, and to both operands of the shift operators, as specified by their respective subclauses.

Second, we have the usual arithmetic conversions (6.3.1.8):

[T]he integer promotions are performed on both operands. Then the following rules are applied to the promoted operands:

  • If both operands have the same type, then no further conversion is needed.

Finally, we have the operator. For example, multiplication says (6.5.5):

The usual arithmetic conversions are performed on the operands.

Thus, in the expression a8 * b8, both operands are promoted to int by the integer promotions, then "no further conversion is needed", and so the result of the expression has type int as well.

It is not necessary to perform the integer promotions, if the result is exactly the same without them as it would be with the integer promotions (that's an instance of the as-if rule, the implementation may do things anyway it wants, if it is indistinguishable from the way the standard prescribes).

The specification of the arithmetic operators (6.5.5, 6.5.6) says that the integer promotions are performed on the operands, so you can rely on "as if".

You cannot be absolutely sure that the int16_t operation doesn't overflow, however, since int itself may be only 16 bits.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top