Skip to main content

Command Palette

Search for a command to run...

Promotion, Conversion and Casts

Published
4 min readView as Markdown

Promotion

  • char or short values (signed or unsigned) are promoted to int (or unsigned) before anything else happens

    • this is done because int is assumed to be the most efficient integral datatype, and it is guaranteed that no information will be lost by going from a smaller datatype to a larger one

    • examples:

      • even if ch is a char, the 'z' value in ch = 'z' is converted to datatype int before being assigned to ch

      • as a more graphic illustration, sizeof('z') returns 4 (on a machine with 8 bit bytes and 32 bit ints)

      • similarly, if stuff is a short and a is a char, stuff = a causes the value from a to be promoted to int

      • promotion doesn't change the size of a variable:

          {
              char ch;
              int before, after;
        
              ch = 'a';
              before = sizeof(ch);
              ch = ch + 1;
              after = sizeof(ch);
          }
        

        sets both before and after to 1 even though, when evaluating ch = ch + 1, the value of ch is promoted to int before adding 1

Conversion

  • after integral promotion, the arguments to an operator are checked

  • if both are the same datatype, evaluation proceeds

  • if the arguments are of different datatypes, conversion will occur:

    • otherwise, if either operand is a long double, the other operand is converted to long double

    • otherwise, if either operand is a double, the other operand is converted to double

    • otherwise, if either operand is a float, the other operand is converted to float

    • otherwise, if either operand is an unsigned long, the other operand is converted to unsigned long

    • otherwise, if one operand is a long and the other is unsigned, one of two things can happen:

      • if sizeof(long) == sizeof(unsigned) (and therefore long has a maximum value less than the maximum value of an unsigned, then both operands are converted to unsigned long

      • if sizeof(long) > sizeof(unsigned), the unsigned operand is converted to long

    • otherwise, if either operand is a long, the other operand is converted to long

    • otherwise, if either operand is an unsigned, the other operand is converted to unsigned

    • otherwise, both operands are evaluated as ints

  • conversion spreads from left to right to raise an expression to the largest datatype:

    • in an entirely int context, 40 / 17 * 13 / 3 would evaluate to 8 (40 / 17 rounds to 2, 2 * 13 = 26, 26 / 3 rounds to 8)

    • to evaluate 40 / 17 * 13 / 3.0

      • 40 / 17 again rounds to 2

      • 2 * 13 = 26

      • but the 3.0 forces the final division into a double context and thus 26.0 / 3.0 = 8.666...

    • if we move the decimal point to the 13 (40 / 17 * 13.0 / 3), the result will still be 8.666... because:

      • 40 / 17 rounds to 2

      • the 13.0 forces the multiplication to a double but 2.0 * 13.0 still equals 26.0

      • and the 26.0 still forces the final division into a double context and 26.0 / 3.0 = 8.666...

    • if we move the decimal point to the 17 (40 / 17.0 * 13 / 3), the result now becomes 10.196... because:

      • the 17.0 forces the initial division into a double context and 40.0 / 17.0 = 2.352...

      • 2.352... * 13.0 = 30.588...

      • and 30.588... / 3.0 = 10.196...

Casts

  • the type of an expression can be forced using casts.

  • a cast is simply any valid datatype enclosed in parentheses and placed next to a constant, variable or expression

  • examples:

    • (float)11 / 3 forces the entire expression to be evaluated in a floating point context, producing a result of 3.6666...

    • to evaluate ((int)7.5 * 2) / (long double)5

      • first, the cast forces 7.5 to an int 7

      • the multiplication is done in an integer context yielding 14

      • the cast forces 5 to a long double 5.0

      • which forces the division to be done in a long double context

      • leading to a final result of 14.0 / 5.0 or 2.8

    • note that casts (as in other conversions) only force conversion at their level, so (float)(40 / 17 * 13 / 3) would still evaluate to 8.0 because the entire expression inside the parentheses takes place in an int context, after which it is cast to a float

7 views

More from this blog

P

Programming Tutorials

89 posts