Cliquez ici pour retirer la feuille de style si vous souhaitez imprimer ce document (ou en cas de problème d'affichage).
Variables, expressions, types
An instruction is an operation the CPU can perform and that can modify the memory For example, to add 2 and 3, four informations must be given to the CPU:- where the value 2 is store ?
- where is the value 3 is store ?
- where we want to store the result ?
- which operation we want to perform (here +)
It exists instructions with 0, 1, 2, 3... operands. As C is a portable language, a C instruction does not necessarily corresponds to a single CPU instruction. For the remaining, "instruction" will be use to designate a C instruction ie a list of words that terminates with a ;
C instructions are grouped into blocks, delimited by { }
To begin, let us consider that some of these blocks can be named. A named block is a function. The first block to be executed is the block named main : main(){inst1; inst2; ...;}
To designate the operations, C uses key words: (+,-,/,+=,=,==,...). To designates operands (that can be either values or memory adresses) C uses the notions of variable and type. Declaring a variable means reserving a name to designate a specific memory address, while specifying in the same time the type of the data that will be store there, that is to say, its size in byte (example integer = 32 or 64 bits on most of the CPUs) and the operation to use for some of them that are written the same way (example: the integer division is different from the division on real numbers, but both are written in C with /).
Back with the memory
For the program, the memory is an infinite array of bytes. This array is not use randomly. The beginning contains reserved data for the process (pid, ppid, file descriptors, environment...). Then came the program instructions. After came an area called the stack. Finally, the last address (the biggest that can be encoded with an integer value) is the beginning of the heap, that grows from the right to the left.
On the following, we will just represent the stack part, and vertically (the bottom being the first address of the stack). Let get back to the add example and look at what happens on the stack:
The first step consist in memory reservation, giving names to reserved area (in order to be able to use them late): int a; int b; int res; The type must be written in order to know the size of the area to reserve. This is called variable declarions. Then, the reserved area can be fill: a=2; b=3; This is called variable initializations.
The "a+b;" instruction is correct. However there is no side effect on the stack. In order to be usefull, the result of this instruction must be affected to a variable: res=a+b;
Some C specific rules
- Variables must be declared only at a block beginning (not mixed with other instructions)
- The "existence" of the variable, ie the code from where its name exists, is limited to this block
Types
C is a strongly typed language. Every expressions have a type. Allowed type are structures, alias (with typedef) and primitive types : int, char, float,... A type is characterized by its size in bytes. The special function sizeof() permits to obtain the size of a type. The instruction "sizeof(char);" for example is equal to 1. The C specification only says:
- char type size is 1 (in fact 1 octet, which is use to be equal to 1 byte)
- 1 = sizeof(char) = sizeof(unsigned char) ≤ sizeof(short int) = sizeof(unsigned short int) ≤ sizeof(int) = sizeof(unsigned int) ≤ sizeof(long) = sizeof(unsigned long) ≤ sizeof(float) ≤ sizeof(double) ≤ sizeof(long double)
data type | means | syze (octet/byte) | Range of value | ||||||
char | Character | 1 | -128 à 127 | ||||||
unsigned char | unsigned character | 1 | 0 à 255 | ||||||
short int | short integer | 2 | -32 768 à 32 767 | ||||||
unsigned short int | unsigned short integer | 2 | 0 à 65 535 | ||||||
int | integer |
|
| ||||||
unsigned int | unsigned integer |
|
| ||||||
long int | long integer |
|
| ||||||
unsigned long int | unsigned long integer |
|
| ||||||
float | Floating point number (real) | 4 | 3.4*10^-38 à 3.4*10^38 | ||||||
double | Floating point number double precision | 8 | 1.7*10^-308 à 1.7*10^308 | ||||||
long double | long double | 10 | 3.4*10^-4932 à 3.4*10^4932 |
Les expressions
Formally, an expression is a part of code which begins after a ; and terminates at the next ; Every expressions have a value and can have a side effect (ie modify the stack or more generally the memory). As every expression have value, it is possible to compare them one by one this operators ==, <, > <=, >=; or to assign their value to a variable with =. The combination then is a bigger expression, only the final ; is kept
example
- int a; is an expression. Its value depends on the state of the memory before its execution. Its side effect is to move the stack pointer by sizeof(int) bytes to the right (or the top) and to reserve the name "a" for the block duration;
- a=3; is also an expression. Its value is 3. Its effect is to fill the memory area designated byt "a" with the bits encoding the value 3 for the target machine.
- These two expressions can be combined in one:int a = 3; The resulting expression value is 3. It's side effect is the combination of the two previous effects.
- a==3; is an expression. It s value is 1 if a value is 3, else it is 0. It has no side effect.
Questions :
- Le programme suivant est-il correct au sens de la norme ISO C90 ?