data types
int, char, void, arrays
Primitives
There are only four basic data types in C. The problems come later when custom data types and compound data types come into use.
char
A single byte (8 bits, 00000000 to 11111111 in binary, 0 to 255 in decimal) - enough for a single character.
int
General purpose integer - 2 bytes long. Can store integer (whole number) values between -32,768 and +32,767. If negative numbers are not required, int can be customised to be unsigned int, range 0 to 65,535. Windows compilers may use the macro UINT for unsigned int.
float
Floating point (fractions and decimals). 4bytes long. Suitable for whole or decimal numbers of up to seven significant places - 0.0000001 to 9,999,999.
double
Largest of the primitives - 8 bytes long. Floating point type but with enough space to store fifteen significant places.
The primitives illustrate the history of C programming - current CPU's are 32bit and the next generation are 64bit. Programs that use a lot of single character variables, (char type), may actually run slower on 64bit machines because 56bits of the CPU register are unused, wasting cache space. However, CPU design does take this into account and you should not use this as an excuse to waste memory on variables that use larger types than are remotely necessary. (char[] strings are not a problem.)
Modifiers
As mentioned, unsigned can be used to make better use of the space available. long can also be used to create a 4byte integer without the burden of the floating point. When combined, an unsigned long int has a range from 0 to over 5million. These are called modifiers and allow the compiler to allocate enough memory for these enlarged types from the beginning of the program. One final modifier is const - any primitive or modified primitive can be deemed const. A const value can only be assigned at definition. Any attempt to change a const value later in the program will generate a compiler error. This compares with the #define macro which must be pre-defined before the program is compiled - const allows you to calculate a runtime value and define a new const to store it.
casts
Sometimes, you have a value in a floating point that needs to be passed to a function that only accepts integers. Care is needed here because if you try to convert from a large float to a smaller type, the final value is unpredictable. Your code should check that the float value is LESS than the upper limit of the smaller type before attempting the cast. Another problem is lack of rounding - casting a float of 9.99 results in an integer value of 9, not 10. Remember that the compiler will sometimes cast your variables implicitly by casting the final result to the larger type. This ensures you don't lose data but can cause confusion. Multiplying an integer by a double will result in a double. If you need to force a cast from a larger type to a smaller type and you've checked the size of the larger value, use the syntax:
myint = int(mydouble);
Some complex types
C syntax :
typedef - create an alias for an existing primitive.
typedef unsigned int UINT creates a type called UINT that is exactly equivalent to an unsigned int defined in any other way. const and long modifiers can also be used in a typedef definition.
struct - group variables of any type into a single box. The size of the box is padded so that sizeof(mystruct) always returns a consistent size.
struct ADDRESS {
int housenum;
char firstline[];
char postcode[];
};
ADDRESS home;
home.housenum = 56;
home.postcode = "W1 1AA";
C++ syntax :
class - a development of the C struct that can hold functions as well as variables. Importantly, the C++ class keyword also provides inheritance - one class can inherit variables and functions from another in a strictly controlled manner. This is the basis of OOP.
C++ programs can also use typedef and struct.