Types
The fundamental types in C are char (character), int (integer) and float. Some compilers include the bool data type.
  1. char
    char is the character type. It usually hold 8 bits which stores an encoded character. The standard encoding scheme is ASCII. However, other encoding schemes such as EBCDIC can be used.

    In C you can manipulate variables defined as character using the same operations that apply to integers.
    //
    // Character types
    //
    #include <iostream>
    #include <iomanip>
    
    using namespace std;
    
    int main () 
    {
        char letter;
        int x;
        
        letter='x';
        cout << "The size of the char is " << sizeof(char) << endl;
        for(x=0;x<5;x++) {
    	 cout << letter << "\t" 
                  << int(letter) << "\t" i
                  << hex << int(letter) << endl;
             cout << dec;
             letter++;
        }
        system("pause");
        return 0;
    }            
    

    The size of the char is 1
    x       120     78
    y       121     79
    z       122     7a
    {       123     7b
    |       124     7c
    Press any key to continue . . .
    

  2. bool The bool type takes one byte and stores a value of true (1) or false(0).
    //
    // Boolean types
    //
    #include <iostream>
    #include <iomanip>
    
    using namespace std;
    
    int main () 
    {
        char letter;
        bool fv,tv;
        
        tv=true;
        fv=false;
        
        cout << "The size of a bool is " << sizeof(bool) << endl;
        cout << "true\t"  << tv << "\t" 
    	 << int(tv) << "\t" 
             << hex << int(tv) << dec << endl;
        cout << "false\t" << fv << "\t" 
             << int(fv) << "\t" i
             << hex << int(fv) << dec << endl;
        system("pause");
        return 0;
    }            
    

    The size of a bool is 1
    true    1       1       1
    false   0       0       0
    Press any key to continue . . .
    

  3. int
    int is the integer data type. Integers are represented in binary format.
    1. Binary numbers may be stored in either 1's or 2's complement form. Most machines use 2' complement. To form 1's complement just invert the bits. For two complement invert the bits and add one. An interesting property of one's complement is that there are two ways to represent zero.
    2. The size of an int is 4.
    3. In binary arithmetic subtraction is done by complementing a number and then adding it. To add binary numbers use the following rules.
       0 + 0 = 0
       0 + 1 = 1
       1 + 0 = 1
       1 + 1 = 10
      
      for ease 1 + 1 + 1 = 11
      
      to add 7 + 4
      
      4       0000 0000 0000 0000 0000 0000 0000 0100
      7       0000 0000 0000 0000 0000 0000 0000 0111
      -----------------------------------------------
              0000 0000 0000 0000 0000 0000 0000 1011
      
        
      
      to subtract 7 - 6
      
      First form the complement of 6  
          6 = 0000 0000 0000 0000 0000 0000 0000 0110
      	1111 1111 1111 1111 1111 1111 1111 1001  invert bits
              0000 0000 0000 0000 0000 0000 0000 0001  add one
            -------------------------------------------
              1111 1111 1111 1111 1111 1111 1111 1010  -6
              0000 0000 0000 0000 0000 0000 0000 0111  add 7
             ------------------------------------------
             10000 0000 0000 0000 0000 0000 0000 0001 1
      
      ignore the final carry as it is overflow. 
      


    4. The range of integer variable is determined by the size of the integer. For an integer with n bits the range on a two's complement machine is:

      - 2 n-1 .. 2 n-1 -1

      On a one's complement machine the lower bound becomes

      - 2n-1 -1

      Since most machines use two's complement you can usually expect:
        Bits                 Low                  High
        16               -32,768                32,767
        32        -2,147,483,648         2,147,483,647
      

    5. Overflow
         int k,x;
         k=0x7ffffffa;
          for(x=0;x<10;x++) {
             cout << k << "\t";
             printbinary(k);
             k++;
          }  
      

      2147483642      0111 1111 1111 1111 1111 1111 1111 1010
      2147483643      0111 1111 1111 1111 1111 1111 1111 1011
      2147483644      0111 1111 1111 1111 1111 1111 1111 1100
      2147483645      0111 1111 1111 1111 1111 1111 1111 1101
      2147483646      0111 1111 1111 1111 1111 1111 1111 1110
      2147483647      0111 1111 1111 1111 1111 1111 1111 1111
      -2147483648     1000 0000 0000 0000 0000 0000 0000 0000
      -2147483647     1000 0000 0000 0000 0000 0000 0000 0001
      -2147483646     1000 0000 0000 0000 0000 0000 0000 0010
      -2147483645     1000 0000 0000 0000 0000 0000 0000 0011
      
    6. C++ supports the concept of unsigned integers like

         unsigned int k;
         k=0x7ffffffa;
          for(x=0;x<10;x++) {
             cout << k << "\t";
             printbinary(k);
             k++;
          }  
      

      2147483642      0111 1111 1111 1111 1111 1111 1111 1010
      2147483643      0111 1111 1111 1111 1111 1111 1111 1011
      2147483644      0111 1111 1111 1111 1111 1111 1111 1100
      2147483645      0111 1111 1111 1111 1111 1111 1111 1101
      2147483646      0111 1111 1111 1111 1111 1111 1111 1110
      2147483647      0111 1111 1111 1111 1111 1111 1111 1111
      2147483648      1000 0000 0000 0000 0000 0000 0000 0000
      2147483649      1000 0000 0000 0000 0000 0000 0000 0001
      2147483650      1000 0000 0000 0000 0000 0000 0000 0010
      2147483651      1000 0000 0000 0000 0000 0000 0000 0011
      

    7. The C/C++ compilers accept the integer modifiers short and long for integers, but the implementation is left to the hardware. You are guaranteed that a short will be no bigger than an int and a long will be no smaller than an int.


  4. Float

    1. real numbers are stored as floating point approximations of the number. Floating point numbers are divided into sign bit, exponent and mantissa. In most hardware the mantissa is normalized between with the most significant 1 to the left of the decimal point.The number of bits devoted to the mantissa determines the precision of the number, or how many digits may be represented. The number of bits in the exponent determines the range (magnitude) of the number.
    2. Intel uses the IEEE 754 format

      sign bit
      8 bit exponent
      23 bit mantissa.

      The exponent is stored biased 127. 127 is added to the exponent. Exponents larger than 127 are positive, less than 127 are negative exponents.
    3. Convert 17.125 to floating point.
      1. Convert 17 to Binary
              17 / 2 = 8  r 1
              8  / 2 = 4  r 0
              4  / 2 = 2  r 0
              2  / 2 = 1  r 0
              1  / 2 = 0  r 1  stop read backwards
        
              1710 = 100012
        

      2. Convert .125 to binary
              .125 x 2 = 0.25   0
              .25  x 2 = 0.50   0
              .5   x 2 = 1.0    1
               0   stop when zero or you run out of bits
        
               .12510 = .0012
        

      3. 17.12510 = 10001.0012
      4. Move the decimal point 4 digits to the left (4 = 100)
        1.0001001 x 2100
      5. Bias the exponent by 127
                  0111 1111  (127 in binary)
        	  0000 0100
        	  ----------
                  1000 0011
        
      6. Sign bit =0
      7. Exponent = 10000011
      8. Mantissa = 0001001
      9. 17.125 = 0100 0011 0001 0010 0000 0000 0000 0000= 0x43120000

    4. Other floating float point numbers
      1 = 0  01111111 00000000000000000000000
      2 = 0  10000000 00000000000000000000000
      4 = 0  10000001 00000000000000000000000
      100 = 0  10000101 10010000000000000000000
      0.0001 = 0  01110001 10100011011011100010111
      1.9 = 0  01111111 11100110011001100110011
      -1.9 = 1 01111111 11100110011001100110011
      
  5. Double C++ has a double ( meaning double precision) type that extends the mantissa. Different manufactures use various schemes to divide up the exponent and mantissa. As the following table represents various 64 bit schemes
    VendorExponent bitsLowHighMantissa bitsDecimal Digits
    IEEE11-3083085216
    Cyber11-2933234815
    IBM 30817-79755616
    VAX D7-39385617
    VAX G11-3093075216
    Cray15-246624654814


  6. In representing a floating point number if the exponent exceeds the the maximum we say an overflow has occurred. If the exponent becomes smaller than the minimum, we say an underflow has occurred.
    Floating point overflow.
    #include <iostream.h>
    #include <values.h>
    void main()
    {
      float maxf= MAXFLOAT;
      
      cout << maxf <<end; 
      maxf=maxf+MAXFLOAT;
      cout << maxf <<endl;
    }
    
    3.40282e+38
    infinity
    

    Floating point underflow.
    #include <values.h>
    #include <iostream.h>
    void main()
    {
      float minf= MINFLOAT;
      
      cout << minf << endl;   
      minf=minf/1000000;
      cout << minf << endl;  
    }
    
    1.4013e-45
    0
    

  7. Since floating number numbers are approximations to the actual number there exist a problem with roundoff errors as demonstrated here:
    #include <iostream.h>
    main()
    {
     float value,sum;
     int count;
    
     sum=0.0;
     value=1e-3;
     for(count=0;count<1000;count++) sum+=value;
     cout << sum <<endl;
    
     sum=0.0;
     value=1e-4;
     for(count=0;count<10000;count++) sum+=value;
     cout << sum <<endl;
    
     sum=0.0;
     value=1e-5;
     for(count=0;count<100000;count++) sum+=value;
     cout << sum <<endl;
    }
    
    When this program is run on a 32 and 64 bit words the results are:
     Results
    
     32-bit        64-bit
    
    0.999991      1.000000
    1.000054      1.000000
    1.000990      1.000000
    

  8. When doing floating point arithmetic we are concerned with "what is the smallest value that will make a difference in logical operations?". This is called the machine epsilon. It can be computed:
    #include <iostream.h>
    main()
    {
     double eps;
    
     eps=1.0;
    
     while(1.0+eps > 1.0) eps/=2;
     eps*=2;
     cout << "epsilon = " << eps << endl;
    }
    
    When this was compiled and run a 32 bit architecture the result was:
    epsilon = 2.220446e-16
    On a pentium the result was
    epsilon = 1.084202e-19
    Since the floating point values are approximations, this leads us to an important rule of thumb. NEVER USE EQUALITY TESTS ON FLOATS

  9. Mixed type expressions.
    If the operands are the same type then the result is of that type. If operands are of different types, the "narrow" types are converted to the "widest" type in the expression. This automatic promotion follows the general progression:
    char->short->int->long->float->double
     int k=5;
     float x,y=20.0;
    
     x=y/k;
    
    1. The assignment operator uses the type of the left hand side. This may cause warnings when demotion occurs.
    2. To change the type explicitly use the static_cast notation.
        float x;
        int a=7, b=3;
      
        x=a/b;
      
      What is the result?
        float x;
        int a=7, b=3;
      
        x=static_cast<float>a/b;
      
      Now what is the result?

  10. Size of Variables
    The size of different types can be discovered with the sizeof operator. It returns the size of the variable ( or structure) in bytes (8 bits). The following program will print out the sizes of the different types.
    #include <iostream.h>
    void main()
    {
     cout << "char   " << sizeof(char)   << endl;
     cout << "short  " << sizeof(short)  << endl;
     cout << "int    " << sizeof(int)    << endl;
     cout << "long   " << sizeof(long)   << endl;
     cout << "float  " << sizeof(float)  << endl;
     cout << "double " << sizeof(double) << endl;
    }
    
    I got the following results from running on different architectures:
    Size of Variables
    TypeVaxSunConvexCrayApolloMS VC++
    char 111111
    short 222822
    int 444844
    long 444844
    float 444844
    double888888

    Running on the dev C++ compiler I get:
    char   1
    bool   1
    short  2
    int    4
    long   4
    float  4
    double 8
    Press any key to continue . . .
    

  11. Declaring Variables
    In general variables may be declared inside of a block of code. A block is denoted by { }. Variables inside of a block are local to that block.
    int main()
    {
      int a,b;
      float c;
      char d;
    }
    
    1. Variables may be initialized when declared with the = operator like:
      int main() 
      {
        int a=1;
        float b=1.2e3;
        char c='a';
      }
      
      Local variables are initialized every time the block of code is executed.
      #include <iostream>
      using namespace std;
       
      void f();  // function prototype
       
      int main()
      {
         f();  // call function f
         f();  // call function f
         system("pause");
         return 0;
       
      }
      void f()  // function f
      {
        int localX=1;     // declare and set local varaible
       
        cout << "In Function f " << endl;
        cout << "localX is " << localX << endl;
        localX=2;
        return;
      }
       
      

      In Function f
      localX is 1
      In Function f
      localX is 1
      Press any key to continue . . .
      

  12. Conditions
    #include <limits>
    #include <float.h>
    #include <iostream>
     
    using namespace std;
    int main()
    {
      int max=INT_MAX;
      cout << "The maximum value for an integer is : " << max << endl;
      cout << "Add +1 to go over the max - overflow" << endl;
      max++;
      cout << "Now the value is : " << max << endl;
      cout << endl;
     
      float maxf= FLT_MAX;
      cout << "The Maximum Float Value is : " <<  maxf <<endl;
      cout << "Times 1 million to force overflow" << endl;
      maxf*=1.0e6;
      cout << "After overflow : " << maxf <<endl;
      cout << endl;
      
      float minf=FLT_MIN;
      cout << "The Minimum Float Value is  " << minf << endl;
      cout << "Divide by 1 trillion to force underflow " << endl;
      minf/=1.0e12;
      cout << "After underflow : " << minf << endl;
     
      system("pause");
      return 0;
    }
     
    

    The maximum value for an integer is : 2147483647
    Add +1 to go over the max - overflow
    Now the value is : -2147483648
     
    The Maximum Float Value is : 3.40282e+038
    Times 1 million to force overflow
    After overflow : 1.#INF
     
    The Minimum Float Value is  1.17549e-038
    Divide by 1 trillion to force underflow
    After underflow : 0
    Press any key to continue . . .