Home > other >  Math with different width variables and casting
Math with different width variables and casting

Time:05-17

Consider the following code snippet:

// The assigned numbers are random and not relevant
uint16_t val = 2;
uint32_t sum = 4;

sum  = val; // point 1

sum /= val; // point 2
  1. In this operation, is the val automatically cast to uint32_t? If not, what is faster- casting it or leaving as uint16_t?
  2. In this operation, is the val automatically cast to uint32_t? If not, what is faster- casting it or leaving as uint16_t?

Assume the architecture is 16-bit.

CodePudding user response:

In both cases, the value of val is automatically converted to the larger type uint32_t. The precise behavior depends on the actual size of int.

  • If type int has 15 value bits, the val is converted to uint32_t, preserving the alue, the addition and division are performed using uint32_t arithmetics, which operates modulo 232 and the result is stored into sum.

  • If type int has between 16 and 31 value bits, val is first promoted to int, preserving its value, then the promoted value is converted to uint32_t, again preserving the value because it is positive, and the operation completes as described above.

  • If type int has more than 31 value bits, both sum and val are promoted to int, preserving the values, the addition and division is performed using int signed arithmetics, and the result is converted to uint32_t, modulo 232, for storage into sum.

For the above example values, the result is the same in all cases, but for the example below, the behavior is undefined on a hypothetical architecture where int would have 32 value bits:

uint16_t val = 2;
uint32_t sum = 0xffffffff;

sum  = val; // signed arithmetic overflow if type `int` has 33 bits

These implicit promotions and conversions are not cast operations, you could add explicit casts such as sum = (uint32_t)val; but the behavior would be exactly the same and would have no impact on performance.

If the compiler can determine the value of val at compile time, it will likely compile the expression sum /= val; into a right shift or a multiplication to avoid a costly division. Dividing an unsigned value by a power of 2 is a cheap right shift operation, if the value is signed and potentially negative, the shift must be adjusted. For other non-zero dividends, a multiplication by 2k/val into a larger type is used.

  •  Tags:  
  • c
  • Related