# Promotion, Conversion and Casts

## 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 `int`s)
            
        * 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:
            
            ```c
            {
            	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 `int`s
        
* 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`
