programmation en langage C, Study Guides, Projects, Research of Information Systems Analysis and Design

base de programmation en langage C

Typology: Study Guides, Projects, Research

2018/2019
On special offer
30 Points
Discount

Limited-time offer


Uploaded on 12/03/2019

patrick-gaitou
patrick-gaitou 🇹🇬

1 document

1 / 37

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
Les bases de la
programmation en C
Par Samir OTMANE
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
Discount

On special offer

Partial preview of the text

Download programmation en langage C and more Study Guides, Projects, Research Information Systems Analysis and Design in PDF only on Docsity!

Les bases de la

programmation en C

Par Samir OTMANE

Table des matières

1 Un peu d’histoire -----------------------------------------------------------------

2 La compilation --------------------------------------------------------------------

3 Les composants élémentaires du C -------------------------------------------

3.1.1 Les identificateurs

3.1.2 Les mots-clefs

3.1.3 Les commentaires

4 Structure d'un programme C -------------------------------------------------

5 Les types prédéfinis -------------------------------------------------------------- 8

5.1 Le type caractère

5.2 Les types entiers

5.2 Les types flottants

6 Les constantes ---------------------------------------------------------------------

6.1 Les constantes entières

6.2 Les constantes réelles

6.3 Les constantes caractères

6.4 Les constantes chaînes de caractères

7 Les opérateurs ------------------------------------------------------------------- 10

7.1 L'affectation

7.2 Les opérateurs arithmétiques

7.3 Les opérateurs relationnels

7.4 Les opérateurs logiques booléens

7.5 Les opérateurs logiques bit à bit

7.6 Les opérateurs d'affectation composée

7.7 Les opérateurs d'incrémentation et de décrémentation

7.8 L'opérateur virgule

7.9 L'opérateur conditionnel ternaire

7.10 L'opérateur de conversion de type

7.11 L'opérateur adresse

8 Les instructions de branchement conditionnel ---------------------------- 14

8.1 Branchement conditionnel « if---else »

8.2 Branchement multiple « switch »

1 Un peu d’histoire

Le C a été conçu en 1972 par Dennis Richie et Ken Thompson, chercheurs aux Bell Labs, afin de développer un système d'exploitation UNIX sur un DEC PDP-11. En 1978, Brian Kernighan et Dennis Richie publient la définition classique du C dans le livre The C Programming language [6]. Le C devenant de plus en plus populaire dans les années 80, plusieurs groupes mirent sur le marché des compilateurs comportant des extensions particulières. En 1983, l'ANSI (American National Standards Institute) décida de normaliser le langage ; ce travail s'acheva en 1989 par la définition de la norme ANSI C. Celle-ci fut reprise telle quelle par l'ISO (International Standards Organization) en 1990. C'est ce standard, ANSI C, qui est décrit dans le présent document.

2 La compilation

Le C est un langage compilé (par opposition aux langages interprétés). Cela signifie qu'un programme C est décrit par un fichier texte, appelé fichier source. Ce fichier n'étant évidemment pas exécutable par le microprocesseur, il faut le traduire en langage machine. Cette opération est effectuée par un programme appelé compilateur. La compilation se décompose en fait en 4 phases successives :

1. Le traitement par le préprocesseur : le fichier source est analysé par le préprocesseur qui effectue des transformations purement textuelles (remplacement de chaînes de caractères, inclusion d'autres fichiers source ...). 2. La compilation : la compilation proprement dite traduit le fichier généré par le préprocesseur en assembleur, c'est-à-dire en une suite d'instructions du microprocesseur qui utilisent des mnémoniques rendant la lecture possible. 3. L'assemblage : cette opération transforme le code assembleur en un fichier binaire, c'est-à-dire en instructions directement compréhensibles par le processeur. Généralement, la compilation et l'assemblage se font dans la foulée, sauf si l'on spécifie explicitement que l'on veut le code assembleur. Le fichier produit par l'assemblage est appelé fichier objet. 4. L'édition de liens : un programme est souvent séparé en plusieurs fichiers source, pour des raisons de clarté mais aussi parce qu'il fait généralement appel à des librairies de fonctions standard déjà écrites. Une fois chaque code source assemblé, il faut donc lier entre eux les différents fichiers objets. L'édition de liens produit alors un fichier dit exécutable.

Les différents types de fichiers utilisés lors de la compilation sont distingués par leur suffixe. Les fichiers source sont suffixés par .c, les fichiers prétraités par le préprocesseur par .i, les fichiers assembleur par .s, et les fichiers objet par .o. Les fichiers objets correspondant aux librairies pré-compilées ont pour suffixe .a.

Le compilateur C sous UNIX s'appelle cc. On utilisera de préférence le compilateur gcc du projet GNU. Ce compilateur est livré gratuitement avec sa documentation et ses sources. Par défaut, gcc active toutes les étapes de la compilation. On le lance par la commande gcc [options] fichier.c [-llibrairies]

Par défaut, le fichier exécutable s'appelle a.out. Le nom de l'exécutable peut être modifié à l'aide de l'option -o. Les éventuelles librairies sont déclarées par la chaîne -llibrairie. Dans ce cas, le système recherche le fichier liblibrairie.a dans le répertoire contenant les librairies pré-compilées (généralement /usr/lib/). Par exemple, pour lier le programme avec la librairie mathématique, on spécifie -lm. Le fichier objet correspondant est libm.a. Lorsque les librairies pré-compilées ne se trouvent pas dans le répertoire usuel, on spécifie leur chemin d'accès par l'option -L.

Les options les plus importantes du compilateur gcc sont les suivantes :

-c : supprime l'édition de liens ; produit un fichier objet. -E : n'active que le préprocesseur (le résultat est envoyé sur la sortie standard). -g : produit des informations symboliques nécessaires au débogueur. -Inom-de-répertoire : spécifie le répertoire dans lequel doivent être recherchés les fichiers en-têtes à inclure (en plus du répertoire courant).

-Lnom-de-répertoire : spécifie le répertoire dans lequel doivent être recherchées les librairies précompilées (en plus du répertoire usuel). -o nom-de-fichier : spécifie le nom du fichier produit. Par défaut, le exécutable fichier s'appelle a.out. -O, -O1, -O2, -O3 : options d'optimisations. Sans ces options, le but du compilateur est de minimiser le coût de la compilation. En rajoutant l'une de ces options, le compilateur tente de réduire la taille du code exécutable et le temps d'exécution. Les options correspondent à différents niveaux d'optimisation : -O (similaire à -O) correspond à une faible optimisation, -O3 à l'optimisation maximale. -S : n'active que le préprocesseur et le compilateur ; produit un fichier assembleur. -v : imprime la liste des commandes exécutées par les différentes étapes de la compilation. -W : imprime des messages d'avertissement (warning) supplémentaires. -Wall : imprime tous les messages d'avertissement.

3 Les composants élémentaires du C

Un programme en langage C est constitué des six groupes de composants élémentaires suivants :

  • les identificateurs,
  • les mots-clefs,
  • les constantes,
  • les chaînes de caractères,
  • les opérateurs,
  • les signes de ponctuation.

On peut ajouter à ces six groupes les commentaires, qui sont enlevés par le préprocesseur.

3.1 Les identificateurs

Le rôle d'un identificateur est de donner un nom à une entité du programme. Plus précisément, un identificateur peut désigner :

  • un nom de variable ou de fonction,
  • un type défini par typedef, struct, union ou enum,
  • une étiquette.

Un identificateur est une suite de caractères parmi :

  • les lettres (minuscules ou majuscules, mais non accentuées),
  • les chiffres,
  • le ``blanc souligné'' (_).

Le premier caractère d'un identificateur ne peut pas être un chiffre. Par exemple, var1, tab_23 ou _deb sont des identificateurs valides ; par contre, 1i et i:j ne le sont pas. Il est cependant déconseillé d'utiliser « _ » comme premier caractère d'un identificateur car il est souvent employé pour définir les variables globales de l'environnement C.

ATTENTION : Les majuscules et minuscules sont différenciées.

Le compilateur peut tronquer les identificateurs au-delà d'une certaine longueur. Cette limite dépend des implémentations, mais elle est toujours supérieure à 31 caractères. (Le standard dit que les identificateurs externes, c'est-à-dire ceux qui sont exportés à l'édition de lien, peuvent être tronqués à 6 caractères, mais tous les compilateurs modernes distinguent au moins 31 caractères).

if (x != 0) { z = y / x; t = y % x; }

Une instruction composée d'un spécificateur de type et d'une liste d'identificateurs séparés par une virgule est une déclaration. Par exemple,

int a; int b = 2, c; double x = 2.38e4; char message[80];

ATTENTION : En C, toute variable doit faire l'objet d'une déclaration avant d'être utilisée.

Un programme C se présente de la façon suivante :

[directives au préprocesseur] [déclarations de variables externes] [fonctions secondaires]

main() { déclarations de variables internes, instructions }

La fonction principale main peut avoir des paramètres formels. On supposera dans un premier temps que la fonction main n'a pas de valeur de retour. Ceci est toléré par le compilateur mais produit un message d'avertissement quand on utilise l'option -Wall de gcc.

Les fonctions secondaires peuvent être placées indifféremment avant ou après la fonction principale. Une fonction secondaire peut se décrire de la manière suivante :

type ma_fonction ( arguments ) {déclarations de variables internes instructions }

Cette fonction retournera un objet dont le type sera type (à l'aide d'une instruction comme return objet;). Les arguments de la fonction obéissent à une syntaxe voisine de celle des déclarations : on met en argument de la fonction une suite d'expressions type objet séparées par des virgules. Par exemple, la fonction secondaire suivante calcule le produit de deux entiers :

int produit(int a, int b) { int resultat;

resultat = a * b; return(resultat); }

5 Les types prédéfinis

Le C est un langage typé. Cela signifie en particulier que toute variable, constante ou fonction est d'un type précis. Le type d'un objet définit la façon dont il est représenté en mémoire.

La mémoire de l'ordinateur se décompose en une suite continue d'octets. Chaque octet de la mémoire est caractérisé par son adresse, qui est un entier. Deux octets contigus en mémoire ont des adresses qui diffèrent d'une unité. Quand une variable est définie, il lui est attribué une adresse. Cette variable correspondra à une zone mémoire dont la longueur (le nombre d'octets) est fixée par le type.

La taille mémoire correspondant aux différents types dépend des compilateurs ; toutefois, la norme ANSI spécifie un certain nombre de contraintes.

Les types de base en C concernent les caractères, les entiers et les flottants (nombres réels). Ils sont désignés par les mots-clefs suivants :

char int float double short long unsigned

5.1 Le type caractère

Le mot-clef char désigne un objet de type caractère. Un char peut contenir n'importe quel élément du jeu de caractères de la machine utilisée. La plupart du temps, un objet de type char est codé sur un octet ; c'est l'objet le plus élémentaire en C. Le jeu de caractères utilisé correspond généralement au codage ASCII (sur 7 bits). La plupart des machines utilisent désormais le jeu de caractères ISO-8859 (sur 8 bits), dont les 128 premiers caractères correspondent aux caractères ASCII. Les 128 derniers caractères (codés sur 8 bits) sont utilisés pour les caractères propres aux différentes langues.

Une des particularités du type char en C est qu'il peut être assimilé à un entier : tout objet de type char peut être utilisé dans une expression qui utilise des objets de type entier. Par exemple, si c est de type char, l'expression c

  • 1 est valide. Elle désigne le caractère suivant dans le code ASCII. Ainsi, le programme suivant imprime le caractère 'B'.

main() { char c = 'A'; printf("%c", c + 1); }

5.2 Les types entiers

Le mot-clef désignant le type entier est int. Un objet de type int est représenté par un mot ``naturel'' de la machine utilisée, 32 bits pour un DEC alpha ou un PC Intel.

Le type int peut être précédé d'un attribut de précision ( short ou long ) et/ou d'un attribut de représentation ( unsigned ).Un objet de type short int a au moins la taille d'un char et au plus la taille d'un int. En général, un short int est codé sur 16 bits. Un objet de type long int a au moins la taille d'un int (64 bits sur un DEC alpha, 32 bits sur un PC Intel).

5.3 Les types flottants

Les types float , double et long double servent à représenter des nombres en virgule flottante. Ils correspondent aux différentes précisions possibles.

en octal du caractère. On peut aussi écrire '\xcode-hexa' où code-hexa est le code en hexadécimal du caractère (cf. page X). Par exemple, '\33' et '\x1b' désignent le caractère escape. Toutefois, les caractères non-imprimables les plus fréquents disposent aussi d'une notation plus simple :

\n nouvelle ligne \r retour chariot \t tabulation horizontale \f saut de page \v tabulation verticale \a signal d'alerte \b retour arrière

6.4 Les constantes chaînes de caractères

Une chaîne de caractères est une suite de caractères entourés par des guillemets. Par exemple,

" Ceci est une chaîne de caractères "

Une chaîne de caractères peut contenir des caractères non imprimables, désignés par les représentations vues précédemment. Par exemple,

"ligne 1 \n ligne 2"

A l'intérieur d'une chaîne de caractères, le caractère " doit être désigné par ". Enfin, le caractère \ suivi d'un passage à la ligne est ignoré. Cela permet de faire tenir de longues chaînes de caractères sur plusieurs lignes. Par exemple,

"ceci est une longue longue longue longue longue longue longue longue
chaîne de caractères"

7 Les opérateurs

7.1 L'affectation

En C, l'affectation est un opérateur à part entière. Elle est symbolisée par le signe =. Sa syntaxe est la suivante : variable = expression Le terme de gauche de l'affectation peut être une variable simple, un élément de tableau mais pas une constante. Cette expression a pour effet d'évaluer expression et d'affecter la valeur obtenue à variable. De plus, cette expression possède une valeur, qui est celle expression. Ainsi, l'expression i = 5 vaut 5.

L'affectation effectue une conversion de type implicite : la valeur de l'expression (terme de droite) est convertie dans le type du terme de gauche.Par exemple, le programme suivant

main() { int i, j = 2; float x = 2.5; i = j + x; x = x + i; printf("\n %f \n",x); }

imprime pour x la valeur 6.5 (et non 7), car dans l'instruction i = j + x;, l'expression j + x a été convertie en entier.

7.2 Les opérateurs arithmétiques

Les opérateurs arithmétiques classiques sont l'opérateur unaire - (changement de signe) ainsi que les opérateurs binaires

  • addition
  • soustraction
  • multiplication / division % reste de la division (modulo)

Ces opérateurs agissent de la façon attendue sur les entiers comme sur les flottants. Leurs seules spécificités sont les suivantes :

Contrairement à d'autres langages, le C ne dispose que de la notation / pour désigner à la fois la division entière et la division entre flottants. Si les deux opérandes sont de type entier, l'opérateur / produira une division entière (quotient de la division). Par contre, il délivrera une valeur flottante dès que l'un des opérandes est un flottant. Par exemple,

float x; x = 3 / 2;

affecte à x la valeur 1. Par contre

x = 3 / 2.;

affecte à x la valeur 1.5.

L'opérateur % ne s'applique qu'à des opérandes de type entier. Si l'un des deux opérandes est négatif, le signe du reste dépend de l'implémentation, mais il est en général le même que celui du dividende.

Notons enfin qu'il n'y a pas en C d'opérateur effectuant l'élévation à la puissance. De façon générale, il faut utiliser la fonction pow(x,y) de la librairie math.h pour calculer x^y.

7.3 Les opérateurs relationnels

supérieur = supérieur ou égal < strictement inférieur <= inférieur ou égal == égal != différent

Leur syntaxe est expression1 op expression

Les deux expressions sont évaluées puis comparées. La valeur rendue est de type int (il n'y a pas de type booléen en C); elle vaut 1 si la condition est vraie, et 0 sinon.

ATTENTION : à ne pas confondre l'opérateur de test d'égalité = = avec l'opérateur d'affection =. Ainsi, le programme

main() { int a = 0; int b = 1;

7.7 Les opérateurs d'incrémentation et de décrémentation

Les opérateurs d'incrémentation ++ et de décrémentation -- s'utilisent aussi bien en suffixe (i++) qu'en préfixe (++i). Dans les deux cas la variable i sera incrémentée, toutefois dans la notation suffixe la valeur retournée sera l'ancienne valeur de i alors que dans la notation préfixe se sera la nouvelle. Par exemple,

int a = 3, b, c; b = ++a; /* a et b valent 4 / c = b++; / c vaut 4 et b vaut 5 */

7.8 L'opérateur virgule

Une expression peut être constituée d'une suite d'expressions séparées par des virgules : expression1, expression2, ... , expressionN

Cette expression est alors évaluée de gauche à droite. Sa valeur sera la valeur de l'expression de droite. Par exemple, le programme

main() { int a, b; b = ((a = 3), (a + 2)); printf("\n b = %d \n",b); }

imprime b = 5.

7.9 L'opérateur conditionnel ternaire

L'opérateur conditionnel? est un opérateur ternaire. Sa syntaxe est la suivante : condition? expression1 : expression Cette expression est égale à expression1 si condition est satisfaite, et à expression2 sinon. Par exemple, l'expression

x >= 0? x : -x

correspond à la valeur absolue d'un nombre. De même l'instruction

m = ((a > b)? a : b);

affecte à m le maximum de a et de b.

7.10 L'opérateur de conversion de type

L'opérateur de conversion de type, appelé cast, permet de modifier explicitement le type d'un objet. On écrit

(type) objet

Par exemple,

main() { int i = 3, j = 2; printf("%f \n",(float)i/j); }

retourne la valeur 1.5.

7.11 L'opérateur adresse

L'opérateur d'adresse & appliqué à une variable retourne l'adresse mémoire de cette variable. La syntaxe est

& objet

8 Les instructions de branchement conditionnel

On appelle instruction de contrôle toute instruction qui permet de contrôler le fonctionnement d'un programme. Parmi les instructions de contrôle, on distingue les instructions de branchement et les boucles. Les instructions de branchement permettent de déterminer quelles instructions seront exécutées et dans quel ordre.

8.1 Branchement conditionnel « if---else »

La forme la plus générale est celle-ci :

if (expression1 ) instruction else if (expression2 ) instruction ... else if (expressionN ) instructionN else instructionM

avec un nombre quelconque de else if ( ... ). Le dernier else est toujours facultatif. La forme la plus simple est

if (expression ) instruction

Chaque instruction peut être un bloc d'instructions.

8.2 Branchement multiple « switch »

Sa forme la plus générale est celle-ci :

switch (expression ) {case constante1: liste d'instructions 1 break; case constante2: liste d'instructions 2 break; ... case constanteN: liste d'instructions N break; default: liste d'instructions M break; }

expr 1; while (expr 2 ) {instruction expr 3; }

Par exemple, pour imprimer tous les entiers de 0 à 9, on écrit :

for (i = 0; i < 10; i++) printf("\n i = %d",i);

A la fin de cette boucle, i vaudra 10. Les trois expressions utilisées dans une boucle for peuvent être constituées de plusieurs expressions séparées par des virgules. Cela permet par exemple de faire plusieurs initialisations à la fois. Par exemple, pour calculer la factorielle d'un entier, on peut écrire :

int n, i, fact; for (i = 1, fact = 1; i <= n; i++) fact *= i; printf("%d! = %d \n",n,fact);

On peut également insérer l'instruction fact *= i; dans la boucle for ce qui donne :

int n, i, fact; for (i = 1, fact = 1; i <= n; fact *= i, i++); printf("%d! = %d \n",n,fact);

On évitera toutefois ce type d'acrobaties qui n'apportent rien et rendent le programme difficilement lisible.

10 Les instructions de branchement non conditionnel

10.1 Branchement non conditionnel « break »

On a vu le rôle de l'instruction break ; au sein d'une instruction de branchement multiple switch. L'instruction break peut, plus généralement, être employée à l'intérieur de n'importe quelle boucle. Elle permet d'interrompre le déroulement de la boucle, et passe à la première instruction qui suit la boucle. En cas de boucles imbriquées, break fait sortir de la boucle la plus interne. Par exemple, le programme suivant :

main() { int i; for (i = 0; i < 5; i++) { printf("i = %d\n",i); if (i == 3) break; } printf("valeur de i a la sortie de la boucle = %d\n",i); }

imprime à l'écran

i = 0 i = 1 i = 2 i = 3 valeur de i à la sortie de la boucle = 3

10.2 Branchement non conditionnel « continue »

L'instruction continue permet de passer directement au tour de boucle suivant, sans exécuter les autres instructions de la boucle. Ainsi le programme

main() { int i; for (i = 0; i < 5; i++) { if (i == 3) continue; printf("i = %d\n",i); } printf("valeur de i a la sortie de la boucle = %d\n",i); }

imprime

i = 0 i = 1 i = 2 i = 4 valeur de i à la sortie de la boucle = 5

11 Les fonctions d'entrées-sorties classiques

Il s'agit des fonctions de la librairie standard stdio.h utilisées avec les unités classiques d'entrées-sorties, qui sont respectivement le clavier et l'écran. Sur certains compilateurs, l'appel à la librairie stdio.h par la directive au préprocesseur

#include <stdio.h>

n'est pas nécessaire pour utiliser printf et scanf.

11.1 La fonction d'écriture « printf »

La fonction printf est une fonction d'impression formatée, ce qui signifie que les données sont converties selon le format particulier choisi. Sa syntaxe est

printf(" chaîne de contrôle ", expression1 , ... , expressionN );

La chaîne de contrôle contient le texte à afficher et les spécifications de format correspondant à chaque expression de la liste. Les spécifications de format ont pour but d'annoncer le format des données à visualiser. Elles sont introduites par le caractère %, suivi d'un caractère désignant le format d'impression. Les formats d'impression en C sont donnés dans la table 1suivante.

scanf("%x",&i); printf("i = %d\n",i); }

Si on entre au clavier la valeur 1a, le programme affiche i = 26.

format type d'objet pointé représentation de la donnée saisie %d int décimale signée %hd short int décimale signée %ld long int décimale signée %u unsigned int décimale non signée %hu unsigned short int décimale non signée %lu unsigned long int décimale non signée %o int octale %ho short int octale %lo long int octale %x int hexadécimale %hx short int hexadécimale %lx long int hexadécimale %f float flottante virgule fixe %lf double flottante virgule fixe %Lf long double flottante virgule fixe %e float flottante notation exponentielle %le double flottante notation exponentielle %Le long double flottante notation exponentielle %g float flottante virgule fixe ou notation exponentielle %lg double flottante virgule fixe ou notation exponentielle %Lg long double flottante virgule fixe ou notation exponentielle %c char caractère %s char* chaîne de caractères

Table 2: Formats de saisie pour la fonction scanf

11.3 Impression et lecture de caractères

Les fonctions getchar et putchar permettent respectivement de lire et d'imprimer des caractères. Il s'agit de fonctions d'entrées-sorties non formatées.

La fonction getchar retourne un int correspondant au caractère lu. Pour mettre le caractère lu dans une variable caractere, on écrit caractere = getchar();

Lorsqu'elle détecte la fin de fichier, elle retourne l'entier EOF (End Of File), valeur définie dans la librairie stdio.h. En général, la constante EOF vaut -1.

La fonction putchar écrit caractere sur la sortie standard : putchar(caractere);

Elle retourne un int correspondant à l'entier lu ou à la constante EOF en cas d'erreur.

12 Les types composés

A partir des types prédéfinis du C (caractères, entiers, flottants), on peut créer de nouveaux types, appelés types composés, qui permettent de représenter des ensembles de données organisées.

12.1 Les tableaux

Un tableau est un ensemble fini d'éléments de même type, stockés en mémoire à des adresses contiguës.

La déclaration d'un tableau à une dimension se fait de la façon suivante : type nom-du-tableau[nombre-éléments]; où nombre-éléments est une expression constante entière positive. Par exemple, la déclaration int tab[10]; indique que tab est un tableau de 10 éléments de type int. Cette déclaration alloue donc en mémoire pour l'objet tab un espace de 10 × 4 octets consécutifs.

Pour plus de clarté, il est recommandé de donner un nom à la constante nombre-éléments par une directive au préprocesseur, par exemple #define nombre-éléments 10

On accède à un élément du tableau en lui appliquant l'opérateur []. Les éléments d'un tableau sont toujours numérotés de 0 à nombre-éléments -1. Le programme suivant imprime les éléments du tableau tab :

#define N 10 main() { int tab[N]; int i; ... for (i = 0; i < N; i++) printf("tab[%d] = %d\n",i,tab[i]); }

Un tableau correspond en fait à un pointeur vers le premier élément du tableau. Ce pointeur est constant. Cela implique en particulier qu'aucune opération globale n'est autorisée sur un tableau. Notamment, un tableau ne peut pas figurer à gauche d'un opérateur d'affectation. Par exemple, on ne peut pas écrire ``tab1 = tab2;''. Il faut effectuer l'affectation pour chacun des éléments du tableau :

#define N 10 main() { int tab1[N], tab2[N]; int i; ... for (i = 0; i < N; i++) tab1[i] = tab2[i]; }

On peut initialiser un tableau lors de sa déclaration par une liste de constantes de la façon suivante : type nom-du-tableau[N] = {constante1,constante2,...,constanteN};

Par exemple, on peut écrire

#define N 4 int tab[N] = {1, 2, 3, 4}; main() {