Programmation en C
John Samuel
CPE Lyon
Année: 2026-2027
Courriel: john.samuel@cpe.fr
Donnez des exemples de logiciels écrits en C
Le langage C est un langage de programmation :
Remarque : pas de classes — ce n'est pas un langage orienté objet.
Extensions de fichiers : .c, .h
static_assert.bool, true,
false, static_assert, alignof,
thread_local, nullptr, constexpr ; retrait des
déclarations de fonctions sans prototype.-std=c17, -std=c23 ou
-std=gnu23.| Caractéristique | Langage C | Python |
|---|---|---|
| Paradigme de programmation | Impératif, procédural | Multiparadigme (impératif, orienté objet, fonctionnel) |
| Typage | Statique (typage fort) | Dynamique (typage fort). Les annotations de type (3.5+) ne sont pas vérifiées à l'exécution : un outil externe (mypy) est nécessaire |
| Syntaxe | Syntaxe stricte et rigide | Syntaxe simple et lisible |
| Performance | Performant, optimisé pour les performances | Moins performant, interprété |
| Gestion de la mémoire | Besoin de gérer manuellement la mémoire | Gestion automatique de la mémoire (ramasse-miettes) |
| Portabilité | Portable, mais nécessite une compilation spécifique pour chaque plateforme | Hautement portable grâce à son interpréteur |
Source : Wikidata Query Service, copie d'écran du 12 septembre 2022.
/* Fichier: bonjour1.c
* affiche 'Bonjour le Monde!!!' à l'écran.
* auteur: John Samuel
* Ceci est un commentaire sur plusieurs lignes
*/
#include
<stdio.h> // headers
// Ceci est un commentaire
sur une ligne
int main()
{
printf("Bonjour le Monde
!!!\n");
return
0;
}
Objectif : Ce code utilise des commentaires, inclut le fichier d'en-tête <stdio.h> pour l'utilisation de printf, définit la fonction main comme point d'entrée, utilise printf pour afficher un message, et renvoie 0 pour indiquer une exécution sans erreur.
/* Fichier: bonjour2.c
* affiche un message à l'écran en utilisant une variable
* auteur: John Samuel
* Ceci est un commentaire
sur plusieurs lignes
*/
#include <stdio.h> // headers
int main()
{
int annee = 2026;
//déclaration d'une variable
printf("Bonjour le Monde!!! C'est l'annee %d", annee);
return 0;
}
Objectif : Ce code déclare une variable annee, utilise printf pour afficher un message incluant la valeur.
int main(void) { ... }
int main(int argc, char *argv[]) { ... }
() signifie enfin (void).0 ou EXIT_SUCCESS, sinon EXIT_FAILURE.
$ gcc bonjour1.c
$./a.out
Bonjour le Monde!!!
$ gcc -o bonjour bonjour2.c
$./bonjour
Bonjour le Monde!!! C'est l'annee 2026
Pour voir tous les avertissements (*warnings*) pendant la compilation, vous pouvez utiliser les options -Wall et -Wextra.
$ gcc -Wall -Wextra -o bonjour bonjour2.c
| Norme | Option | Avec extensions GNU |
|---|---|---|
| C99 | -std=c99 | -std=gnu99 |
| C11 | -std=c11 | -std=gnu11 |
| C17 / C18 | -std=c17 | -std=gnu17 |
| C23 (publiée en 2024) | -std=c23 | -std=gnu23 |
Attention : la norme par défaut dépend du compilateur installé
(GCC 15 utilise gnu23). Précisez-la toujours. Pour C89/C90 : -std=c90.
$ gcc -std=c17 -Wall -Wextra -pedantic \
-g -O1 -fsanitize=address,undefined \
-o programme programme.c
Règle : un avertissement est une erreur qui n'a pas encore eu lieu.
$ gcc -std=c17 -Wall -Wextra -pedantic -c prog.c
$ clang -std=c17 -Wall -Wextra -pedantic -c prog.c
$ gcc -std=c17 -fanalyzer -c prog.c
// Ceci est un commentaire sur une ligne (c99)
/* Ceci est un
* commentaire sur
* quatre lignes
*/
Les types de base en C sont les fondations sur lesquelles sont construites toutes les variables et données dans ce langage de programmation.
| Types | Mots clés | Exemples |
|---|---|---|
| caractères | char | 'h', 'a', ... |
| entiers | short, int, long, long long | ...,-1,0,1,... |
| nombres en flottant | float, double, long double | 3.14, 3.14e23 |
| énumérations | enum | ETUDIANT, STAGIAIRE |
Le choix de stocker des données en un octet, deux octets, quatre octets ou huit octets dépend principalement de la précision nécessaire pour représenter les données.
| Types | Mots-clés |
|---|---|
| caractère | signed char, unsigned char |
| entier | signed short, signed int, signed long, signed long long, unsigned short, unsigned int, unsigned long, unsigned long long |
Remarque : La taille des types de base en C n'est pas standardisée car elle dépend de l'architecture matérielle sous-jacente du système sur lequel le code est exécuté, ce qui permet d'optimiser l'utilisation de la mémoire et les performances pour chaque plate-forme.
Les variables de type "char" en C sont utilisées pour stocker des caractères, mais elles peuvent également être qualifiées de "signed" (signé) ou "unsigned" (non signé) pour déterminer si elles peuvent représenter des valeurs négatives (signées) ou uniquement des valeurs positives (non signées).
char my_char_var1 = 'a';
signed char my_char_var2 = -125;
unsigned char my_char_var3 = 225;
Remarque: Remarquez-bien l'utilisation du tiret bas (_) en nommant les
variables
char my_char_var = 'a';
unsigned char my_uchar_var = 234;
short my_short_var = -12;
unsigned short my_ushort_var = 65535;
int my_int_var = 12;
unsigned int my_uint_var = 3456;
long my_long_var = -1234553L;
unsigned long my_ulong_var = 234556UL;
long long my_llong_var = 1123345LL;
unsigned long long my_ullong_var = 1234567ULL;
float my_float_var = 3.14f;
double my_double_var = 3.14E-12;
long double my_long_double_var = 3.14E-22L;
Les énumérations en C sont un moyen de définir un nouveau type de données personnalisé pour représenter un ensemble fini de valeurs entières nommées. Elles sont utiles pour rendre le code plus lisible et compréhensible.
enum status {ETUDIANT, STAGIAIRE}; // ETUDIANT = 0, STAGIAIRE = 1
enum status s = ETUDIANT;
enum status {ETUDIANT=1, STAGIAIRE}; // STAGIAIRE = 2
enum status {ETUDIANT=1, STAGIAIRE=14, ENSEIGNANT}; // ENSEIGNANT = 15
enum boolean {FAUX=0, VRAI};
Remarque: les constantes d'une enum sont de type int ; le type entier sous-jacent de l'énumération est choisi par le compilateur (C23 permet de l'imposer : enum status : unsigned char {...})
L'intervalle minimum et maximum de types de base en utilisant limits.h
| Mots clés | Intervalle |
|---|---|
| signed char | [SCHAR_MIN, SCHAR_MAX] |
| unsigned char | [0, UCHAR_MAX] |
| Mots clés | Intervalle |
|---|---|
| (signed) short int | [SHRT_MIN, SHRT_MAX] |
| unsigned short int | [0, USHRT_MAX] |
| (signed) int | [INT_MIN, INT_MAX] |
| unsigned int | [0, UINT_MAX] |
| Mots clés | Intervalle |
|---|---|
| (signed) long | [LONG_MIN, LONG_MAX] |
| unsigned long | [0, ULONG_MAX] |
| (signed) long long | [LLONG_MIN, LLONG_MAX] |
| unsigned long long | [0, ULLONG_MAX] |
L'intervalle minimum et maximum de types flottant en utilisant float.h
| Mots clés | Intervalle |
|---|---|
| float | [FLT_MIN, FLT_MAX] |
| double | [DBL_MIN, DBL_MAX] |
| long double | [LDBL_MIN, LDBL_MAX] |
sizeof (char) //type
sizeof (my_uchar_var) //variable
printf("sizeof(char): %zu\n",
sizeof (char));
printf("sizeof(long long int): %zu\n",
sizeof (long long int));
printf("sizeof(my_char_var): %zu\n",
sizeof (my_char_var));
Remarque 1: sizeof donne la taille d'une variable en octets ou d'un type de données.
Remarque 2: La valeur retournée peut varier, mais la taille d'une variable de type caractère est de 1 octet.
Remarque 3: La valeur retournée est du type size_t, un
entier non signé dont la largeur dépend de la plate-forme. Le code de conversion portable est
"%zu" (C99) — pas "%lu".
#include <stdint.h>
int8_t a; // exactement 8 bits, signé
uint32_t b; // exactement 32 bits, non signé
uintptr_t p; // contient un pointeur
int reste le bon choix.
#include <inttypes.h>
printf("%zu\n", sizeof(int)); // size_t
printf("%" PRIu64 "\n", (uint64_t) n); // uint64_t
size_t. %lu ne l'est pas :
il n'est correct que si size_t est exactement un unsigned long.<inttypes.h> fournit PRId32, PRIu64, PRIx16... qui se
concatènent avec la chaîne de format.
printf("%d",
my_int_var);
printf("%f",
my_float_var);
| Mots clés | Code de conversion |
|---|---|
| char | c |
| unsigned char | hhu |
| short | hd |
| unsigned short | hu |
| Mots clés | Code de conversion |
|---|---|
| int | d, i |
| unsigned int | u |
| long int | ld |
| unsigned long int | lu |
| Mots clés | Code de conversion |
|---|---|
| long long int | lld |
| unsigned long long int | llu |
| float, double | f, F, e, E, g, G, a, A |
un float passé à printf est converti en
double : les mêmes codes servent pour les deux |
|
| long double | Lf, LF, Le, LE, Lg, LG |
| chaîne de caractères | s |
| Caractère | Code de conversion |
|---|---|
| Saut de ligne (nouvelle ligne) | \n |
| Tabulation | \t |
| Retour chariot | \r |
printf("%d\n", sizeof(x)); // faux : sizeof donne un size_t
printf("%zu\n", sizeof(x)); // correct
-Wall active -Wformat qui le signale.printf(message) quand
message est une variable : c'est la vulnérabilité de chaîne de format.
Écrivez printf("%s", message).%b affiche un entier en binaire.La notation binaire en C permet de représenter des nombres en utilisant uniquement les chiffres 0 et 1, en préfixant les valeurs binaires par "0b", ce qui facilite la manipulation des données au niveau des bits.
Attention : les littéraux
0b... ne sont normalisés que depuis C23 ; avant, c'était une extension GNU
refusée par -std=c17 -pedantic.
int
valeur = 0b10100100;
La notation octale en C permet de représenter des nombres en utilisant la base octale, c'est-à-dire en utilisant les chiffres de 0 à 7, en préfixant les valeurs octales par "0".
int
valeurb = 0b10100100;
int
valeuro = 0244;
printf("notation octale: %o\n", valeurb);
printf("notation octale: %o\n", valeuro);
La notation hexadécimale en C permet de représenter des nombres en utilisant la base hexadécimale, c'est-à-dire en utilisant les chiffres de 0 à 9 et les lettres de A à F, en préfixant les valeurs hexadécimales par "0x".
int
valeurb = 0b10100100;
int
valeurx = 0xa4;
printf("notation hexadecimale: %x\n",
valeurb);
printf("notation hexadecimale: %x\n",
valeurx);
Les opérateurs arithmétiques (+, -, *, /,
%) effectuent les opérations mathématiques sur des valeurs numériques.
| Opérateur | Objectif |
|---|---|
| + | addition |
| - | soustraction |
| * | multiplication |
| / | division |
| % | reste de la division entière (modulo) |
int
a = 20,
b = 10;
| Opérateur | Exemple | Résultat |
|---|---|---|
| + | a + b | 30 |
| - | a - b | 10 |
| * | a * b | 200 |
| / | a / b | 2 |
| % | a % b | 0 |
Les opérateurs relationnels (<, <=, >,
>=, ==, !=) comparent deux valeurs et renvoient
1 (vrai) ou 0 (faux). Ils servent à écrire les conditions.
| Opérateur | Objectif |
|---|---|
| < | inférieur |
| <= | inférieur ou égal |
| > | supérieur |
| >= | supérieur ou égal |
| == | égal |
| != | différent |
int
a = 20,
b = 10;
| Opérateur | Exemple | Résultat |
|---|---|---|
| < | a < b | 0 |
| <= | a <= b | 0 |
| > | a > b | 1 |
| >= | a >= b | 1 |
| == | a == b | 0 |
| != | a != b | 1 |
Remarque: Une valeur différente de zéro est considérée comme VRAIE et la valeur zéro est considérée comme FAUSSE.
Les opérateurs logiques en C, tels que "&&" (ET logique), "||" (OU logique) et "!" (NON logique), sont utilisés pour combiner des expressions booléennes et effectuer des opérations de logique booléenne, ce qui permet de prendre des décisions conditionnelles complexes en évaluant plusieurs conditions simultanément dans les programmes.
int
a = 20,
b = 0;
| Opérateur | Objectif | Exemple | Résultat |
|---|---|---|---|
| ! | Négation | !a | 0 |
| && | Et | a && b | 0 |
| || | Ou | a || b | 1 |
Remarque: Une valeur différente de zéro est considérée comme VRAIE et la valeur zéro est considérée comme FAUSSE.
Les opérateurs d'incrémentation en C, "++" (incrémentation) et "--" (décrémentation), sont utilisés pour augmenter ou diminuer la valeur d'une variable numérique de 1, ce qui facilite les itérations et les mises à jour de variables dans les boucles et les calculs.
int
a = 20,
b = 0;
| Opérateur | Exemple | Résultat |
|---|---|---|
| a++ | b = a++ | a = 21, b = 20 |
| ++a | b = ++a | a = 21, b = 21 |
| a-- | b = a-- | a = 19, b = 20 |
| --a | b = --a | a = 19, b = 19 |
Les opérateurs de manipulation de bits — & (ET), | (OU),
^ (OU exclusif), ~ (NON) — travaillent bit à bit. Ils servent au masquage
et à la gestion de bits individuels.
| Bit 1 | Bit 2 | & | | | ^ (XOR) |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 1 | 1 |
| 1 | 0 | 0 | 1 | 1 |
| 1 | 1 | 1 | 1 | 0 |
Remarque: Les valeurs ci-dessus (0 et 1) sont des bits binaires et non des valeurs entières.
int
a = 0b01000100;
| Opérateur | Objectif | Exemple | Résultat |
|---|---|---|---|
| ~ | Négation | ~a | 0xffffffbb |
| & | ET | a & 0x4 | 0x4 |
| | | OR | a | 0x2 | 0x46 |
| ^ | XOR | a ^ 0x4 | 0x40 |
| << | décalage à gauche | a << 1 | 0x88 |
| >> | décalage à droite | a >> 1 | 0x22 |
unsigned int masque = 0b1010'0110; // littéral binaire
unsigned int n = 1'000'000; // séparateur de chiffres
printf("%b\n", masque); // affichage binaire
' groupe aussi les chiffres décimaux et hexadécimaux : il ne change
pas la valeur, seulement la lisibilité.<stdbit.h> : stdc_count_ones,
stdc_leading_zeros, stdc_bit_width,
stdc_has_single_bit.
1 << 31 // int signé : comportement indéfini
1u << 31 // correct
x << 32 // int de 32 bits : comportement indéfini
-fsanitize=undefined détecte les deux à l'exécution.a op=
b équivaut à a
= a
op b. Existe aussi pour les bits :
&=, |=, ^=, <<=,
>>=.
| Opérateur | Objectif | Exemple |
|---|---|---|
| = | affectation | a = b |
| += | addition | a += b |
| -= | soustraction | a -= b |
| *= | multiplication | a *= b |
| /= | division | a /= b |
| %= | modulo | a %= b |
| Opérateur | Objectif | Exemple |
|---|---|---|
| &= | ET | a &= b |
| |= | OU | a |= b |
| ^= | XOR | a ^= b |
| <<= | décalage à gauche | a <<= b |
| >>= | décalage à droite | a >>= b |
Remarque: a op = b ::- a = a op b
if (condition) {
...
}
_Bool existe (bool via <stdbool.h>) ; depuis C23
bool, true et false sont des mots-clés.
int
a = 20,
b = 0;
if (a >
b) {
printf("a est supérieur à b");
}
L'objectif est de vérifier si la valeur de a est supérieure à celle de b et d'afficher un message si la condition est vraie.
Les instructions if...else if...else exécutent un bloc en fonction de plusieurs conditions alternatives.
if (condition1) {
...
} else if (condition2) {
...
} else {
...
}
Trois pièges classiques du if en C :
if (a = 0) { ... } // affectation, pas comparaison : toujours faux
if (a == 0); { ... } // le ';' termine le if : le bloc s'exécute toujours
if (a == 0)
x = 1; y = 2; // y = 2 n'est pas dans le if : pas d'accolades
-Wall signale les deux premiers cas
(-Wparentheses, -Wempty-body) : lisez les avertissements.else final qui
traite le cas imprévu évite bien des surprises.
int
a = 20,
b = 0;
if (a >
b) {
printf("a est supérieur à b");
} else if (a <
b) {
printf("a est inférieur à b");
} else {
printf("a égale b");
}
switch sélectionne une action à exécuter selon la valeur de l'expression fournie.
switch (expression) {
case valeur1 : instructions1
case valeur2 : instructions2
...
default : instructionsn
}
switch (expression) {
case valeur1 : instructions1
case valeur2 : instructions2
...
default : instructionsn
}
int
a = 20;
switch (a) {
case 10 : instructions1
break;
case 20 : instructions2
case 30 : instructions3
break;
...
default : instructionsn
}
Remarque:Le code exécute instructions2 et continue à exécuter instructions3 car il n'y a pas de break après instructions2.
Que sera-t-il affiché à l'écran suite à l'exécution de ce programme?
if (1) {
printf("Salut\n");
} else {
printf("Bonsoir\n");
}
for(initialisation;condition;actualisation){
...
}
La boucle for répète un bloc de code en trois étapes :
Ces étapes permettent de créer des boucles flexibles qui peuvent être utilisées pour parcourir des éléments d'une liste, effectuer des calculs répétitifs, ou exécuter des actions itératives. La boucle for est couramment utilisée pour simplifier la gestion des itérations dans un programme.
for(initialisation;condition;actualisation){
...
}
int
a = 0;
for( a = 0;
a < 10;
a++){
...
}
L'objectif de ce code est d'initialiser la variable a à 0, puis de répéter un bloc de code tant que a est inférieur à 10, en augmentant la valeur de a à chaque itération.
int
a = 0;
for(;
a < 10;
){
...
}
L'objectif de ce code est de répéter un bloc de code tant que la variable a est inférieure à 10, en utilisant une initialisation préalable de a à 0 et en omettant l'actualisation de a à l'intérieur de la boucle.
Remarque: Une ou toutes les instructions d'initialisation, de condition ou d'actualisation peuvent être omises.
int
a = 0;
for( a = 0;
a < 10;
a++){
...
a += 2 ;
...
}
L'objectif de ce code est d'initialiser la variable a à 0, puis de répéter un bloc de code tant que a est inférieur à 10, en augmentant la valeur de a de 2 à chaque itération à l'intérieur de la boucle, tout en incrémentant a de 1 avec l'opérateur a++ à chaque fin d'itération.
La boucle while maintient l'exécution d'un bloc de code tant que la condition entre les parenthèses reste vraie.
while(condition){
...
}
int
a = 20;
while(a > 0){
...
a--;
...
}
Ce code maintient la répétition d'un bloc de code tant que la valeur de la variable a est supérieure à 0, en la décrémentant à chaque itération.
int
a = 0;
while(a < 20){
...
a++;
...
}
Ce code vise à répéter un bloc de code tant que la valeur de la variable a est inférieure à 20, en l'incrémentant à chaque itération.
La boucle do..while garantit l'exécution d'un bloc de code au moins une fois avant de répéter son exécution tant que la condition spécifiée reste vraie.
do{
...
} while(condition);
int
a = 20;
do{
...
a --;
...
} while(a > 0);
Ce code exécute un bloc de code au moins une fois, puis le répète tant que la valeur de la variable a est supérieure à 0, en décrémentant a à chaque itération.
int
a = 0;
do{
...
a ++;
...
} while(a < 20);
Ce code garantit l'exécution d'un bloc de code au moins une fois, suivi de répétitions tant que la valeur de la variable a est inférieure à 20, en l'incrémentant à chaque itération.
L'instruction break interrompt prématurément une boucle (for, while, do...while) ou un switch : le programme sort immédiatement de la structure, sans attendre la fin de la condition.
do{
...
if (condition 1) {
...
break;
}
...
} while(condition 2);
do{
...
if (condition 1) {
...
break;
}
...
} while(condition 2);
Ce code vise à exécuter un bloc de code au moins une fois, puis à répéter son exécution tant que condition 2 est vraie, tout en utilisant break pour sortir de la boucle si condition 1 est satisfaite.
L'instruction continue abandonne l'itération en cours et passe directement à la suivante, sans sortir de la boucle.
do{
...
if (condition 1) {
...
continue;
}
...
} while(condition 2);
Attention : avec while et do...while, l'actualisation doit être faite avant le continue, sinon la boucle ne se termine jamais.
do{
...
if (condition 1) {
...
continue;
}
...
} while(condition 2);
Ce code a pour objectif d'exécuter un bloc de code au moins une fois, puis de le répéter tant que condition 2 est vraie, en utilisant continue pour sauter le reste du code dans une itération si condition 1 est satisfaite.
while(condition 1){
...
if (condition 2) {
...
break;
}
...
};
Dans ce code, l'objectif est d'exécuter un bloc de code tant que condition 1 est vraie, en utilisant break pour sortir de la boucle si condition 2 est satisfaite à l'intérieur de cette boucle.
while(condition 1){
...
if (condition 2) {
...
continue;
}
...
};
Dans ce code, l'objectif est d'exécuter un bloc de code tant que condition 1 est vraie, en utilisant continue pour passer à l'itération suivante de la boucle si condition 2 est satisfaite à l'intérieur de cette boucle.
for(initialisation;condition 1;actualisation){
...
if (condition 2) {
...
break;
}
...
};
L'objectif de ce code avec la boucle "for" est d'initialiser une variable, puis de répéter un bloc de code tant que condition 1 est vraie, en utilisant break pour sortir de la boucle si condition 2 est satisfaite à l'intérieur de celle-ci.
for(initialisation;condition 1;actualisation){
...
if (condition 2) {
...
continue;
}
...
};
L'objectif de ce code avec la boucle "for" est d'initialiser une variable, puis de répéter un bloc de code tant que condition 1 est vraie, en utilisant continue pour sauter le reste du code dans une itération si condition 2 est satisfaite à l'intérieur de la boucle.
Écrivez un programme qui affiche 0..20 en ordre croissant et décroissant utilisant for, while et do..while.
Écrivez une boucle infinie en utilisant for, while et do..while.
Les tableaux sont des structures de données permettant de stocker un ensemble de valeurs du même type sous un même nom, organisées de manière séquentielle.
Les tableaux à deux indices sont des structures de données qui permettent de stocker des données dans une matrice rectangulaire.
Les tableaux à deux indices sont utiles pour stocker des données tabulaires, des images, des matrices, etc.
Les tableaux à plusieurs indices sont des structures de données permettant de stocker des données dans des dimensions multiples.
Les tableaux à plusieurs indices sont utilisés pour stocker des données tridimensionnelles, telles que des voxels dans une image 3D, des matrices 3D, des jeux de données multidimensionnels, etc.
Pour déclarer un tableau, spécifiez le type des éléments qu'il contiendra, suivi du nom du tableau et de sa taille entre crochets.
par exemple
int tableau[5];
déclare un tableau d'entiers de taille 5.
char nom[20];
déclare un tableau de caractères (ou une chaîne de caractères) de taille 20.
Remarque: le langage C n'a pas de type nommé string : une chaîne est un tableau de char terminé par '\0'.
Les tableaux ont une taille fixe à la déclaration, qui ne peut pas être modifiée pendant l'exécution.
Exemple :
int itableau[20];
float ftableau[20];
double dtableau[20];
Objectif :
Exemple :
int i;
int tableau[20];
for ( i = 0;
i < 20; i++) {
tableau[i] =
i;
}
{} et séparées par des virgules.[] vides indiquent que la taille est déduite du nombre
d'éléments fournis.Exemple :
int prix[5] = {
11, 12, 13, 14, 15 };
int chambres[] = {
301, 302, 303 };
char message[] = "Bonjour Le Monde!!";
Remarque: nous n'avons pas écrit la taille de chambres ni de message.
Exemple :
int prix[5] = {
11, 12, 13, 14, 15 };
sizeof (prix) // 5 * sizeof(int)
Exemple :
int chambres[] = {
301, 302, 303 };
sizeof (chambres) // 3 * sizeof(int)
Exemple :
char message[] = "Bonjour Le Monde!!";
sizeof (message) // (18 + 1 pour le caractère nul '\0') * sizeof(char)
int t[10] = { 0 }; // tous les éléments à 0
int u[10] = { [0] = 1, [9] = 5 }; // les autres à 0
int jours[12] = { [0] = 31, [1] = 28 };
{ 0 } est donc la façon
habituelle de mettre un tableau entier à zéro.
int prix[2][2] = {
{11, 12},
{13, 14}
};
sizeof (prix) // 2 * 2 * sizeof(int)
int chambres[][2] = {
{201, 202},
{301, 302}
};
sizeof (chambres) // 2 * 2 * sizeof(int)
Remarque: Nous n'avons pas précisé le nombre de lignes pour chambres.
int chambres[][2] = {
{201, 202},
{301, 302}
};
sizeof (chambres) // 2 * 2 * sizeof(int)
Pourquoi peut-on omettre le nombre de lignes, mais jamais le nombre de colonnes ?
i * 2 + j depuis le début.void f(int t[][2]) est accepté, void f(int t[][]) non.
int t[10];
sizeof(t) // 40 : la taille du tableau
sizeof(t) / sizeof(t[0]) // 10 : le nombre d'éléments
void f(int t[]) { sizeof(t) // 8 sur une machine 64 bits : c'est un pointeur ! }
-Wsizeof-pointer-div et -Wsizeof-array-argument en signalent une
partie.