Newer
Older
# Structures de contrôle: `switch`{.C} .. `case`{.C} (1/2)
```C
switch (expression) {
case constant-expression:
instructions;
break; // optionnel
case constant-expression:
instructions;
break; // optionnel
// ...
default:
instructions;
}
```
# Structures de contrôle: `switch`{.C} .. `case`{.C} (2/2)
```C
int x = 0;
switch (x) {
case 0:
case 1:
printf("0 ou 1\n");
break;
case 2:
printf("2\n");
break;
default:
printf("autre\n");
}
```
**Dangereux, mais c'est un moyen d'avoir un "ou" logique dans un case.**
## [Quiz: `switch ... case`{.C}](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1033916)
```C
for (expression1; expression2; expression3) {
instructions;
}
```
```C
int sum = 0; // syntaxe C99
for (int i = 0; i < 10; i++) {
sum += i;
}
for (int i = 0; i != 1; i = rand() % 4) { // ésotérique
printf("C'est plus ésotérique.\n");
}
```
- `continue`{.C} saute à la prochaine itération d'une boucle.
int i = 0;
while (i < 10) {
if (i == 3) {
continue;
}
printf("%d\n", i);
i += 1;
}
- `break`{.C} quitte le bloc itératif courant d'une boucle.
```C
for (int i = 0; i < 10; i++) {
if (i == 3) {
break;
}
printf("%d\n", i);
}
```
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# Représentation des variables en mémoire (1/2)
## La mémoire
* La mémoire est:
- ... un ensemble de bits,
- ... accessible via des adresses,
+------+----------+----------+------+----------+------+------+
| bits | 00110101 | 10010000 | .... | 00110011 | .... | .... |
+======+==========+==========+======+==========+======+======+
| addr | 2000 | 2001 | .... | 4000 | .... | .... |
+------+----------+----------+------+----------+------+------+
- ... gérée par le système d'exploitation.
- ... séparée en deux parties: **la pile** et **le tas**.
## Une variable
* Une variable, `type a = valeur`{.C}, possède:
- un type (`char`{.C}, `int`{.C}, ...),
- un contenu (une séquence de bits qui encode `valeur`{.C}),
- une adresse mémoire (accessible via `&a`{.C}),
- une portée.
# Représentation des variables en mémoire (2/2)
{width=100%}
- Les parties indépendantes d'un programme.
- Permettent de modulariser et compartimenter le code.
type identificateur(paramètres) {
// variables optionnelles
// type expression == type
return expression;
```C
int max(int a, int b) {
if (a > b) {
return a;
} else {
return b;
- Il existe un type `void`{.C}, "sans type", en C.
- Il peut être utilisé pour signifier qu'une fonction ne retourne rien, ou qu'elle n'a pas d'arguments.
- `return`{.C} utilisé pour sortir de la fonction.
- Exemple:
```C
void show_text(void) { // second void optionnel
printf("Aucun argument et pas de retour.\n");
return; // optionnel
}
void show_text_again() { // c'est pareil
printf("Aucun argument et pas de retour.\n");
}
```
## Prototypes de fonctions
- Le prototype donne la **signature** de la fonction, avant qu'on connaisse son implémentation.
- L'appel d'une fonction doit être fait **après** la déclaration du prototype.
```C
int max(int a, int b); // prototype
int max(int a, int b) { // implémentation
if (a > b) {
return a;
} else {
return b;
}
}
```
## Arguments de fonctions
- Les arguments d'une fonction sont toujours passés **par copie**.
- Les arguments d'une fonction ne peuvent **jamais** être modifiés.
```C
void set_to_two(int a) { // a: nouvelle variable
// valeur de a est une copie de x
// lorsque la fonction est appelée, ici -1
a = 2; // la valeur de a est fixée à 2
} // a est détruite
int main() {
int x = -1;
set_to_two(x); // -1 est passé en argument
// x vaudra toujours -1 ici
}
```
## Arguments de fonctions: pointeurs
- Pour modifier un variable, il faut passer son **adresse mémoire**.
- L'adresse d'une variable, `x`{.C}, est accédé par `&x`{.C}.
- Un **pointeur** vers une variable entière a le type, `int *x`{.C}.
- La syntaxe `*x`{.C} sert à **déréférencer** le pointeur (à accéder à la mémoire pointée).
## Exemple
```C
void set_to_two(int *a) {
// a contient une copie de l'adresse de la
// variable passée en argument
*a = 2; // on accède à la valeur pointée par a,
// et on lui assigne 2
} // le pointeur est détruit, pas la valeur pointée
int main() {
int x = -1;
set_to_two(&x); // l'adresse de x est passée
// x vaudra 2 ici
}
```
## [Quiz: Les fonctions](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1038560)
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
<!-- TODO quiz;
```C
void set_to_two(int *a) {
a = 2;
}
int main() {
int x = -1;
set_to_two(&x);
}
void add_two(int *a) {
*a += 2;
}
int main() {
int x = -1;
add_two(&x);
}
void add_two(int a) {
a += 2;
printf("%d", a);
}
int main() {
int x = -1;
add_two(&x);
}
``` -->
- Point d'entrée du programme.
- Retourne le code d'erreur du programme:
- 0: tout s'est bien passé.
- Pas zéro: problème.
- La valeur de retour peut être lue par le shell qui a exécuté le programme.
- `EXIT_SUCCESS`{.C} et `EXIT_FAILURE`{.C} (de `stdlib.h`) sont des valeurs de retour **portables** de programmes C.
## Exemple
```C
int main() {
// ...
if (error)
return EXIT_FAILURE;
else
return EXIT_SUCCESS;
}
```
- Le code d'erreur est lu dans le shell avec `$?`{.bash}
```bash
$ ./prog
$ echo $?
0 # tout s'est bien passé par exemple
$ if [ $? -eq 0 ]; then echo "OK" ; else echo "ERROR"; fi
ERROR # si tout s'est mal passé
```