Unless otherwise specified on a case by case basis, these notes have been taken upon reading Kernighan B, W and D. M. Ritchie. Le langage C, Norme ANSI., 2nd edition. Translated into French (original title: The C programming language) by J.-F. Groff and E. Mottier. Masson, Paris and Prentice Hall, London, 1997.
Variable types
There are four basic variable types:
- There are char, which can optionally be unsigned.
- There are int, which can optionally be signed/unsigned and short/long, with the following constraints:
- 16 bits <= short int <= int <= long int
- 32 bits <= long int
- There are floats.
- There are doubles, which can optionally be long.
Sizes of these different types are platform-dependent (check <limits.h> and <float.h> for more information).
One can use suffixes on numerical constants to force types: u or U for unsigned, l or L for long, f or F for float. For example: 3.2F (decimal constant are of type double by default).
Order of precedence
The following table is a simplified version of the one that can be found in Kernighan & Ritchie.
| Operator | Associativity |
|---|---|
| () [] -> . | left to right |
| ! ~ ++ -- *(dereferencing) &(referencing) (type) sizeof | right to left |
| * / % | left to right |
| + - | left to right |
| < <= > >= | left to right |
| == != | left to right |
| && | left to right |
| || | left to right |
Pointers
0 is the only integer that can be assigned to or compared with a pointer. It is never a valid address, so it can be used to indicate an invalid pointer. It is better to use NULL for invalid pointers though. NULL is defined in <stdio.h>.
The only arithmetic operations that are allowed with pointers are:
- Assignment of a pointer to another pointer (a cast is needed if the two pointers point on objects of different types).
- Assignment to and comparison with 0.
- Addition and subtraction of a pointer and an integer.
- Subtraction and comparison of two pointers which point on elements of the same array.
Enumerations
By default, enumerated variables are given values 0, 1, 2, etc. In the following example, FALSE will be set to 0 and TRUE will be set to 1.
enum {FALSE, TRUE}
One can change the starting value, for example (FEBRUARY will be set to 2, and so on):
enum {JANUARY=1, FEBRUARY, MARCH, etc.}
Structures
The size of a struct is not necessarily equal to the sum of the sizes of its individual components, because the system may pad (within the memory) some of its individual components for alignment reasons.
Common or tricky sources of errors
Order of evaluation
The arguments in a function call are evaluated in arbitrary order. For example, the behavior of the second statement in what follows is undefined:
n = 2;
printf("%d %d", ++n, n*n)
It may print "3 4" (if n*n is evaluated before ++n), or "3 9" in the other case.
Similarly, the order of evaluation of the operands of mathematically commutable operators (e.g. addition, multiplication) is arbitrary. The same kind of undefined behavior can occur if operands have side effects (such as incrementing a variable that is used in the other operand).
Switch and break
In a switch/case statement, use break at the end of each clause to make sure that no other clause is executed. Otherwise, several clauses may be executed.