Rappels de langage C

Transcription

Rappels de langage C
ESIEE
IN3T01
Abrégé de langage C
2010/2011
Le langage C
Le langage C est le langage de développement lié à UNIX. Le système UNIX est
d'ailleurs écrit à 95% en C.
C est un langage assez proche de la machine, mais portable. Le développement en C
prend en moyenne sept fois moins de temps que le même développement en assembleur par
un programmeur confirmé, et le surcoût en taille mémoire des programmes et en temps
d'exécution n'est de l'ordre que de une fois et demie à deux fois. De plus, sa portabilité en fait
un langage de développement idéal pour l'écriture de systèmes, de SGBD ou d'autres logiciels
applicatifs.
Le langage C a une réputation de difficulté à maintenir qui est due en grande partie à la
tendance de certains programmeurs à utiliser des trucs et astuces permis par C au détriment de
la lisibilité. Cependant, un programme C correctement construit et commenté est aussi facile à
lire qu'un programme écrit dans un langage plus « clair ».
Voici un exemple de programme C, une esquisse de la commande wc d'UNIX qui
compte les caractères, les mots et les lignes d'un fichier, avec la faible définition pour un mot
d'être une suite de caractères sans espace, retour chariot ou tabulation.
[1] #include <stdio.h>
[2] #define OUI 1
[3] #define NON 0
[4] int main(void) {
[5]
int c, nl, nm, nc, dans_un_mot;
[6]
dans_un_mot = NON;
[7]
nl = nm = nc = 0;
[8]
while ((c = getchar()) != EOF) {
[9]
++nc;
[10]
if (c == '\n')
[11]
++nl;
[12]
if (c == ' ' || c == '\n' || c == '\t')
[13]
dans_un_mot = NON;
[14]
else if (dans_un_mot == NON) {
[15]
dans_un_mot = OUI;
[16]
++nm;
[17]
}
[18]
}
[19]
printf ("%d %d %d\n", nl, nm, nc);
[20]
return 0;
[21]}
Les lignes sont numérotées ici pour le besoin de l'explication. Un programme C n'a pas
de numéros de ligne.
JCG
1/21
ESIEE
IN3T01
Abrégé de langage C
2010/2011
Pour compiler sous UNIX ce programme, enregistré sous le nom compte_mots.c,
on utilise la commande
$ cc compte_mots.c <Entrée>
qui appelle le compilateur C et produit si il n'y a pas d'erreur un fichier exécutable
appelé a.out (nom donné par défaut).
Si on veut lui donner un autre nom que a.out (par exemple wc), il suffit d'appeler
$ cc compte_mots.c -o wc <Entrée>
La commande
$ wc < compte_mots.c <Entrée>
nous donnera une sortie du genre
24 75 373
$
Revenons à l'étude du programme source.
La ligne [1] demande au compilateur d'inclure le texte du fichier stdio.h qui se
trouve en général dans le répertoire /usr/include et qui contient des déclarations de
fonctions (comme getchar) et des définitions (comme EOF).
Les lignes [2] et [3] préviennent le compilateur que, chaque fois que dans le texte du
programme il rencontrera le mot OUI (respectivement NON), il devra le remplacer par 1
(respectivement 0). Ces remplacements ne se feront évidemment pas dans les commentaires,
chaînes de caractères constantes ou à l'intérieur d'un mot.
Par convention, tous les programmes C possèdent une fonction appelée main. C'est
cette fonction qui est exécutée au lancement du programme. Dans notre exemple, c'est la seule
fonction du programme. Elle est déclarée ligne [4].
Les fonctions C retournent en général une valeur. Si elles n'en retournent pas, on les
préfixe par void pour éviter une erreur de type warning (erreur mineure, n'empêchant pas
la compilation, mais signalant souvent un défaut).
Les parenthèses vides indiquent que main n'a pas de paramètres. Le texte d'une
fonction est entre deux accolades { et }. Dans le texte de main, il y a cinq déclarations de
variables (ligne [5] ), toutes cinq de type entier (int) et cinq instructions :
– une instruction d'affectation simple à la ligne [6]
– une instruction d'affectation composée ligne [7]
– une instruction de boucle : while...
(ligne [8] à ligne [18]
– une instruction printf d'affichage (ligne [19])
– une instruction de retour (ligne [20])
JCG
2/21
ESIEE
IN3T01
Abrégé de langage C
2010/2011
L'instruction d'affectation composée n'est pas une spécificité, mais simplement la
conséquence qu'en C, l'affectation peut être utilisée dans une expression, avec comme valeur
celle de la partie gauche de l'affectation, et que de plus l'affectation est associative droite à
gauche.
On peut donc écrire des instructions du type :
a = (b = 5)+( c = 2);
qui aura exactement le même résultat que
b = 5; c = 2; a = b + c;
Dans le cas de l'affectation composée du programme, tout se passe comme si l'on avait
écrit :
nl = (nm = (nc = 0));
L'instruction while teste une condition; si elle est vraie, exécute le corps de la boucle,
et ce tant que la condition est vraie. Ici, la condition est :
Est-ce que le caractère lu dans le fichier d'entrée standard (par la fonction
getchar())et stocké dans c (par l'affectation) est différent du caractère signalant la fin de
fichier (désigné par EOF). Si oui, c'est à dire si un caractère du fichier vient d'être lu, la boucle
est exécutée. Sinon, on passe à l'instruction suivante (affichage).
Le corps de la boucle while est une instruction, ici composée de trois instructions
encadrées entre accolades :
– incrémentation du compteur de caractère
++nc;
a exactement la même signification que
nc = nc + 1;
mais est plus concise et souvent plus efficace.
– une instruction de test
si le caractère lu (stocké dans c) est égal (==) au caractère de retour
chariot ('\n'), on incrémente le compteur de ligne (++nl).
– une autre instruction de test
si le caractère lu est égal à un espace(' ') ou (||) s'il est égal à un
retour chariot ('\n') ou s'il est égal à une tabulation('\t'),
alors on n'est pas dans un mot (dans_un_mot = NON)
sinon ( c'est à dire si le caractère lu est un non-espace )
si on n'est pas dans un mot (dans_un_mot == NON)
alors on rentre dans un mot (dans_un_mot = OUI)
et on le compte (++nm)
L'instruction d'affichage affiche les trois variables nl, nm, nc, sous un format entier
(%d) séparées par des espaces et suivies d'un retour ligne : "%d %d %d\n"
Enfin, l'instruction return termine le programme et renvoie au système la valeur 0.
JCG
3/21
ESIEE
IN3T01
2010/2011
Abrégé de langage C
1 La syntaxe C
1.1
Les règles d'écriture
1.1.1
Commentaires et espaces
Un commentaire commence par les caractères /* et se termine par */.
Le commentaire /* fin de ligne est accepté par la plupart des compilateurs.
Les commentaires imbriqués sont autorisés par certains compilateurs, mais pas par tous.
Pour séparer les mots C, on peut utiliser des espaces, tabulations, retours ligne ou des
commentaires.
1.1.2
Les identificateurs
Un identificateur nomme une variable, une étiquette ou une fonction.
Il est formé d'une suite alphanumérique commençant par une lettre.
Le tiret de soulignement ( _ ) est considéré comme une lettre.
Attention :
Le langage C distingue les majuscules et les minuscules.
La longueur maximum d'un identificateur dépend des compilateurs (6 minimum,
souvent 32).
Certains identificateurs sont des mots réservés du langage :
auto
break
case
char
continue
default
do
double
else
entry
enum
extern
float
for
goto
if
int
long
register
return
short
sizeof
static
struct
Tableau 1 : les mots réservés du C
JCG
4/21
typedef
switch
union
unsigned
void
while
ESIEE
IN3T01
1.1.3
Abrégé de langage C
2010/2011
Les types simples
Le langage C possède plusieurs types simples pour les données, dont la taille mémoire
en multiple de la taille d'un caractère peut être fournie par l'opérateur sizeof.
- char représente n'importe quel caractère du jeu de caractères utilisé. Un caractère est
représenté sous la forme d'un entier et sa valeur dépend du code (ASCII, EBCDIC,
Unicode, ...)
- short int, int, long int désignent trois types d'entiers en arithmétique
modulo 2n, où n est le nombre de bits utilisés pour représenter un nombre. Les trois types
respectent les règles suivantes :
1 = sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long)
sizeof(short) < sizeof(long)
- unsigned short int , unsigned int, unsigned long int désignent les entiers non signés. Le mot int peut être omis si unsigned, short ou long est
précisé.
– float et double désignent les réels simple et double précision.
1.1.4
Les constantes
Une constante entière s'écrit comme une suite de chiffres. Si elle commence par 0, elle
est considérée comme octale (en base 8), par 0x ou 0X comme hexadécimale(en base 16, les
valeurs de 10 à 15 sont alors représentées par a-f ou A-F). Les constantes de type long se
suffixent par l (la lettre L minuscule) ou L.
Une constante de type caractère s'écrit entre apostrophes simples ( ' ). On utilise la
contre-oblique \ pour représenter les caractères spéciaux selon le tableau suivant :
représentation
caractère
'\n'
'\t'
'\b'
'\r'
'\\'
'\''
'\0'
nouvelle ligne (nl)
tabulation (ht)
retour arrière (bs)
retour chariot (cr)
anti slash
apostrophe
nul
Tableau 2 : les constantes caractères spéciales
De plus, on peut représenter un caractère sous sa forme numérique octale '\ddd' où d
désigne un chiffre octal.
Les constantes chaîne de caractères sont des suites de caractères encadrées par des
double guillemets anglais ( " ). Elles peuvent contenir les caractères spéciaux sous la forme
décrite précédemment avec en plus \" pour inclure un guillemet à l'intérieur de la chaîne.
Le caractère nul ('\0') est ajouté systématiquement à toute constante chaîne.
JCG
5/21
ESIEE
IN3T01
Abrégé de langage C
2010/2011
Les constantes réelles sont traitées en double précision et s'écrivent sous la forme :
partie_entière[.partie_décimale]e[±]exposant
comme par exemple
0.0
-2.71828 6.02e23
1.1.5
Les variables
Une variable est un nom (identificateur) qui permet d'adresser un espace mémoire où
sera stocké le contenu (la valeur) de la variable.
Une variable est déclarée par
nom_type nom_variable;
Le type est nécessaire pour pouvoir réserver une place suffisante pour stocker la valeur
de la variable. La variable existera tant que la fin du bloc dans lequel elle est déclarée n'est pas
atteinte (variable automatique), sauf si elle est déclarée static ou extern, auquel cas
elle existera depuis le début jusqu'à la fin du programme.
1.2
Les expressions et les opérateurs
Une expression est une constante, un identificateur, un élément de tableau, une
référence à une structure ou une union, un appel de fonction ou toute combinaison
d'expressions.
1.2.1
Les opérateurs arithmétiques
+
*
/
%
addition
soustraction
multiplication
division ( entière si les deux opérandes sont entiers)
reste de la division entière (17 % 5 -> 2)
Tableau 3 : les opérateurs arithmétiques
1.2.2
Les opérateurs relationnels
Ils retournent 0 si la comparaison est fausse et 1 si elle est vraie
<
strictement inférieur
<= inférieur ou égal
>
strictement supérieur
>= supérieur ou égal
Tableau 4 : les comparateurs arithmétiques
1.2.3
Les opérateur d'égalité et d'inégalité
Ils retournent 0 si la comparaison est fausse et 1 si elle est vraie
== égal
!= différent
Tableau 5 : les opérateurs d'égalité
JCG
6/21
ESIEE
IN3T01
1.2.4
Abrégé de langage C
2010/2011
Les opérateurs de décalage
Ils décalent l'opérande gauche d'un nombre de bits égal à l'opérande droit
>>
décalage droite (si unsigned, remplissage par des 0,
sinon dépendant du compilateur)
<<
décalage gauche remplissage par des 0
Tableau 6 : les opérateurs de décalage
1.2.5
Les opérateurs bit à bit
Ils réalisent pour les bits de même rang de leurs opérandes l'opération logique indiquée.
&
et logique
|
ou logique
^
ou exclusif
Tableau 7 : les opérateurs bit à bit
1.2.6
Les opérateurs logiques
Ils n'évaluent leur opérande droit qu'en cas de nécessité.
&&
et logique (retourne 1 si les deux opérandes non nuls, 0 sinon)
||
ou logique (retourne 1 si un des opérandes non nul, 0 sinon)
!
non logique (retourne 1 si un des opérandes non nul, 0 sinon)
Tableau 8 : les opérateurs logiques
1.2.7
L'opérateur virgule
expr1, expr2
évalue expr1, puis expr2 et retourne la valeur de expr2
1.2.8
Les opérateurs d'affectation
l_value = expr ;
l_value est une expression permettant de désigner une adresse mémoire
(identificateur de variable, indirection de pointeur, élément de tableau, référence à une
structure ou à une union) , et expr une expression.
l_value et expr sont évaluées et la valeur de expr est rangée à l'endroit défini par
la l_value.
+=
-=
*=
/=
%=
>>=
<<=
&=
^=
|=
effectuent entre leurs deux opérandes l'opération indiquée avant le signe = et range leur
résultat dans leur membre gauche
x += y est équivalent à x = x + y, mais l'adresse de x n'est recherchée qu'une
fois.
JCG
7/21
ESIEE
IN3T01
1.2.9
Abrégé de langage C
2010/2011
L'opérateur conditionnel
expr ? expr1 : expr2
Il évalue expr. Si sa valeur est non nulle, retourne la valeur de expr1 sinon la valeur
de expr2.
1.2.10
Les opérateurs unaires
e représente une expression et v une l_value
opérateur
description
*e
retourne la valeur contenue à l'adresse calculée par e
&v
retourne l'adresse mémoire de la variable v
-e
moins unaire
!e
non logique (si e vaut 0, retourne 1 sinon retourne 0)
~e
non logique bit à bit
++v
incrémente v et retourne sa valeur
--v
décrémente v et retourne sa valeur
v++
retourne la valeur de v, puis l'incrémente
v-retourne la valeur de v, puis le décrémente
(nom_type)e
convertit e dans le type nom_type
sizeof(e)
taille (en char) de e
sizeof(type) taille (en char) d'un objet de type
Tableau 9 : les opérateurs unaires
1.2.11
La conversion de type
Des conversions de type sont effectuées automatiquement à chaque opération ou appel
de fonction.
D'abord, les opérandes char ou short sont convertis en int, et ceux de type float
sont convertis en double
Puis, si l'un des opérandes est double, l'autre est converti en double et le résultat est
de type double.
Sinon, si l'un des opérandes est long, l'autre est converti en long et le résultat est de
type long.
Sinon, si l'un des opérandes est unsigned, l'autre est converti en unsigned et le
résultat est de type unsigned.
Sinon, les deux opérateurs sont de types int et le résultat de type int.
1.2.12
Priorité et ordre d'évaluation.
Le tableau suivant donne l'ordre de priorité, décroissant d'une ligne à la suivante, et le
sens d'évaluation en cas d'opérateurs de même priorité d'une expression.
JCG
8/21
ESIEE
IN3T01
Abrégé de langage C
Opérateur
()
[]
->
.
! ~ ++ -- - (nom_type) * & sizeof
* / %
+ << >>
< <= > >=
== !=
&
^
|
&&
||
?:
= += -= *= ...
,
2010/2011
Sens d'évaluation
→
←
→
→
→
→
→
→
→
→
→
→
←
←
→
Tableau 10 : priorités des opérateurs
2 Le contrôle du programme
2.1
Les instructions de contrôle
L'ordre normal d'exécution des instructions est l'ordre d'écriture de ces instructions. Une
instruction composée est une suite d'instructions, encadrée par des accolades. Sauf précision
contraire, toute instruction peut être considérée comme une instruction composée.
2.1.1
L'instruction if
if (expression) instruction1
ou
if (expression) instruction1 else instruction2
Si la valeur de l'expression est non nulle, c'est instruction1 qui sera
exécutée. Sinon, lorsque la partie else existe, c'est instruction2.
2.1.2
L'instruction switch
switch (expression_de_type_int)
instruction_composée
Selon la valeur de l'expression, le débranchement se fait sur l'une des instructions
de l'instruction composée étiquetée de la manière suivante :
case expression_constante :
ou
default :
JCG
9/21
ESIEE
IN3T01
Abrégé de langage C
2010/2011
Le déroulement se poursuit à l'instruction suivant l'étiquette dont la valeur est égale à la
valeur de l'expression, ou à l'instruction étiquetée default jusqu'à rencontrer une instruction
break; qui débranche sur l'instruction suivant l'instruction switch.
2.1.3
Les itérations
while (expression) instruction
tant que l'expression est évaluée à une valeur non nulle, le programme exécute
l'instruction.
● for (instr1; expr; instr2) instruction
est équivalente à :
instr1
while (expr2) {
instruction
instr2
}
● do instruction while (expr)
est équivalente à
instruction
while(expr) instruction
● break;
permet de sortir d'une l'instruction do, for, while ou switch, d'un niveau
d'imbrication seulement.
● goto etiquette;
permet de débrancher inconditionnellement sur l'instruction de la même fonction
étiquetée par etiquette, du type etiquette : instruction;
● continue;
débranche le programme sur l'itération suivante de boucle for, while ou do.
●
2.2
Les fonctions
Une fonction est un morceau de programme appelable aussi souvent que nécessaire, et
qui rend souvent un programme plus lisible.
● Une fonction est déclarée en spécifiant le type de résultat (void si elle ne retourne
pas de valeur, on l'appelle alors procédure) et le nom de la fonction.
type_de_résultat nom_de_la_fonction(liste_de_paramètres);
● Une fonction est définie en précisant de plus le nom de ses paramètres formels, leurs
types et le corps de la fonction. Une définition peut servir de déclaration.
type_de_résultat nom_de_la_fonction (liste_de_paramètres)
{
corps_de_la_fonction
}
Si le type_de_résultat n'est pas déclaré, la fonction est supposée retourner un
int. Une fonction ne peut pas être définie dans une autre fonction. Le corps de la fonction
JCG
10/21
ESIEE
IN3T01
Abrégé de langage C
2010/2011
commence par la déclaration des variables locales à la fonction. Une variable locale déclarée
static conservera sa valeur d'un appel à l'autre de la fonction. Une instruction return
terminera l'exécution de la fonction. Il peut y avoir plusieurs instructions return dans une
même fonction (mais une seule sera exécutée).
return;
terminera la fonction sans transmettre de valeur
return expr;
terminera la fonction en retournant expr
Une fonction ne peut retourner qu'un seul résultat de type simple (caractère, entier,
flottant, pointeur).
Une fonction peut être appelée dans une instruction ou dans une expression .
Si c'est une instruction, sa valeur de retour est ignorée. Si c'est une expression, sa valeur
de retour est utilisée pour l'évaluation de l'expression.
Une fonction peut s'appeler elle-même (appel récursif).
Lors de l'appel, les arguments réels (ceux du programme appelant) sont copiés
dans l'ordre dans les paramètres formels (les arguments de la déclaration). Les valeurs
transmises peuvent donc être modifiées sans que les paramètres réels soient modifiés.
Par exemple,
int fac1(int n){
int fac2(int n) {
int fac3(int n){
int i, res;
int res;
if (n<=1)
res =1;
res = 1;
return 1;
for(i=2;i<=n;i++)
for(n;n>=2;n--)
else
res = i * res;
res*=n;
return
return res;
return res;
n*fac3(n-1);
}
}
}
L'appel à ces fonctions se fera, par exemple, de la manière suivante :
a = 5; b = 2;
x = fac1(a) / fac2(b) / fac3(a-b);
La première fonction est écrite dans un style classique.
La deuxième se sert du fait que les paramètres ne sont transmis que par valeur, et que n
peut servir à la fois de compteur de boucle et de test.
La troisième utilise la récursivité.
Attention :
Le langage C ne transmet les paramètres de fonction que par copie. Si une modification
intervient dans la fonction, elle n'aura d'effet que sur la copie, pas sur l'original.
Pour modifier la valeur d'un paramètre par l'intermédiaire d'une fonction, on transmet
l'adresse du paramètre à modifier, et on réceptionne cette adresse dans un pointeur.
void triple(int *a) {*a *= 3;}
int x=2;
triple(&x); /* x vaut maintenant 6 */
JCG
11/21
ESIEE
IN3T01
Abrégé de langage C
2010/2011
3 Les types composés et les pointeurs
3.1
Les tableaux
Un tableau est un ensemble de variables de même type.
int a[4] ; déclare 4 variables de type int :
a[0], a[1], a[2] et a[3].
Les éléments d'un tableau sont des l_values et peuvent donc apparaître à gauche d'une
affectation.
Un tableau à deux dimensions est déclaré comme ceci :
char ecran[24][80];
déclare un tableau de 24 lignes (de 0 à 23) de 80 caractères (de 0 à 79).
ecran[i][j]
désignera le caractère j de la ligne i.
Dans les appels de fonctions, la valeur transmise pour un tableau est l'adresse du
premier élément de ce tableau.
Par exemple, les chaînes de caractères étant des tableaux de caractères terminés par
'\0', on peut écrire le programme suivant :
/* recopie la ch2 dans ch1 */
void copie_chaine(char ch1[], char ch2[]) {
/*la taille d'un tableau n'est ici pas nécessaire */
int i;
for (i=0; ((ch1[i] = ch2[i]) != '\0' ; i++) ;
/* le résultat de l'affectation sert au test */
}
3.2
Les pointeurs
3.2.1
Définition
Un pointeur est une variable dont le contenu est l'adresse d'une l_value.
Il est déclaré en précisant le type d'objet sur lequel il pointe :
int *pi;
signifie que pi est destiné à contenir l'adresse d'un int
Un pointeur peut être sans type. Dans ce cas, on le déclare par
void *p;
3.2.2
Opérations
L'opérateur * permet d'accéder à la valeur pointée.
JCG
12/21
ESIEE
IN3T01
Abrégé de langage C
L'opérateur & permet d'obtenir l'adresse d'une l_value.
Par exemple,
int n,z;
int *pn;
La déclaration a pour effet d'attribuer des emplacement
ici A1, A2 et A3 :
variable
n
z
adresse mémoire
A1
A2
contenu
indéterminé indéterminé
2010/2011
mémoire aux variables, notées
pn
A3
indéterminé
pn = &n;
En A3, on stocke la valeur A1 (l'adresse de n)
variable
adresse mémoire
contenu
n
A1
indéterminé
z
A2
indéterminé
pn
A3
A1
z
A2
indéterminé
pn
A3
A1
n = 3;
En A1, on stocke 3
variable
n
adresse mémoire
A1
3
contenu
Les variables n et pn sont initialisées.
Voyons maintenant les opérations éventuelles :
z = *pn;
*pn en tant que valeur signifie la valeur à l'adresse indiquée par le contenu de pn
Le contenu de pn vaut A1. La valeur en A1 est 3, donc z vaut 3
variable
adresse mémoire
contenu
n
A1
3
z
A2
3
pn
A3
A1
*pn = 5
*pn, en tant que l_value signifie la l_value située à l'adresse indiquée par de pn
pn vaut A1. A1 contiendra donc la valeur 5
variable
adresse mémoire
contenu
JCG
n
A1
5
z
A2
3
13/21
pn
A3
A1
ESIEE
IN3T01
Abrégé de langage C
2010/2011
Pour un pointeur unique sur un type simple, les trois opérations possibles sont :
pointeur = &l_value;
/* modifie la valeur du pointeur */
*pointeur = expr;
/* modifie la valeur de l'objet pointé */
l_value = *pointeur;
/* évalue la valeur de l'objet pointé */
3.2.3
Pointeurs et tableaux
Pointeurs et tableaux sont très liés :
char *cp; char colonne[80];
cp = &tampon[0] ou
cp = tampon
sont équivalentes. cp pointe sur le premier élément du tableau.
De même,
cp = &tampon[4] ou
cp = tampon + 4
sont équivalentes. cp pointe sur le cinquième élément du tableau
3.2.4
Arithmétique sur les pointeurs
L'arithmétique sur les pointeurs dépend du type pointé.
Si p est un pointeur de type X, p+1 pointera sur l'élément suivant d'un tableau fictif de
X commençant en p.
3.2.5
Exemples de fonctions
void echanger(int *pi, int *pj) {
int z;
z = *pi;
*pi = *pj;
*pj =z;
}
appelée par
#include <stdio.h>
int main() {
int a=2, b=3;
printf("Avant échange, a=%d b=%d\n", a, b);
echanger(&a,&b);
printf("Après échange, a=%d b=%d\n", a, b);
return 0;
}
JCG
14/21
ESIEE
IN3T01
Abrégé de langage C
2010/2011
void strcpy(char *ch1, char *ch2) {
/* ch1 doit disposer d'assez de place
contenir ch2 */
while (*ch1++ = *ch2++) ;
}
appelée par
#include <stdio.h>
int main() {
char a[5] = "toto";
char *b = "titi";
printf("Avant copie, a=%s b=%s\n", a, b);
strcpy(a, b);
printf("Après copie, a=%s b=%s\n", a, b);
return 0;
}
3.2.6
pour
Allocation dynamique de mémoire
Un pointeur n'est pas obligé d'être initialisé par l'affectation d'une adresse de l_value.
L'allocation dynamique de mémoire permet de demander au système de la mémoire pour
contenir des objets créés par le programme.
La fonction
void *malloc(int n)
demande au système n octets contigus et retourne l'adresse de ces octets.
ptr = malloc(100);
Cette mémoire peut être restituée par un appel à la fonction free
free(ptr);
rend la mémoire occupée par l'objet pointé par ptr.
3.3
Structures et unions
Une structure sert à regrouper des éléments de types différents. Par exemple,
struct personne {
char nom[20];
int age;
}
struct personne p[10], x, y;
déclarera un tableau p de 10 personne et deux variables x et y de type personne.
Pour accéder à un des champs d'une structure, on utilise l'opérateur . (un point)
x.nom sera le tableau de 20 caractères correspondant au nom de x
x.age sera l'entier correspondant à l'age de x.
strcpy(x.nom, "toto");
x.age = 10;
JCG
15/21
ESIEE
IN3T01
Abrégé de langage C
2010/2011
Un pointeur peut pointer sur un objet de type structure :
struct personne *pp;
pp = &x;
L'accès aux champs de la structure pointée se fait par l'opérateur -> :
p->age
est équivalent à
(*p).age
On met des parenthèses, car . est plus prioritaire que * :
*p.age <=> *(p.age)
Les structures peuvent contenir des références à elles-mêmes par l'intermédiaire de
pointeurs :
struct elt_liste {
char c;
struct elt_liste *suivant;
};
Dans ce cas, un élément de liste contiendra un caractère et un pointeur sur l'élément de
liste suivant.
Une union est semblable à une structure, dans le sens où elle contient des objets de
types différents, mais un seul à la fois.
union nombre {
int i;
float r;
} x;
Les champs i et r seront deux façons de consulter ou de modifier le contenu de x.
x.i = 2;
x.r = 3.14;
/* écrase la mémoire occupée par la valeur 3.14 */
Attention : le langage C ne se souvient pas du type de la dernière valeur mémorisée
dans une union : c'est au programme de s'en souvenir.
4 Le préprocesseur C
Avant de compiler un programme, le compilateur C lance un préprocesseur qui modifie
le texte de programme en fonction de directives ( les lignes commençant par #). Une de ses
premières tâches est d'éliminer les commentaires (entre /* et */)
JCG
16/21
ESIEE
IN3T01
4.1
Abrégé de langage C
2010/2011
Constantes et macros
#define identificateur objet
remplacera dans le texte du programme (sauf dans les chaînes de caractères)
identificateur par objet (identificateur, constante, chaîne, opérateur, signe de
ponctuation)
#define NB_COL 80
#define ATTENTION_COL (NB_COL - 10)
Les parenthèses sont mises ici pour éviter que les remplacements dans le texte aient un
effet non désiré.
if (ATTENTION_COL * 2 < 100) ....
sera remplacé mot à mot
if ((NB_COL - 10) * 2 < 100) ....
lui-même remplacé par
if ((80 - 10) * 2 < 100) ....
L'effet aurait été différent sans les parenthèses
#define identificateur(arguments) chaîne
remplacera toutes les occurrences de identificateur(....) par la chaîne
dans laquelle les arguments seront remplacés par les valeurs lues dans le programme :
#define max(a,b) ( (a) > (b) ? (a) : (b) )
4.2
Inclusion de fichier
#include "nom_fichier"
sera remplacé par le contenu du fichier, cherché dans le catalogue courant, puis dans
les catalogues système
#include <nom_fichier>
sera remplacé par le contenu du fichier, cherché dans les catalogues système
4.3
Compilation conditionnelle
Elle permet de disposer de sources qui pourront se compiler sur des machines et/ou des
compilateurs différents, à condition de distinguer les différences dans le texte du programme.
#if condition
texte1
#else
texte2
#endif
permet de compiler l'un ou l'autre des textes suivant que la condition est vérifiée ou non.
#ifdef identificateur
texte
#endif
Le texte ne sera compilé que si identificateur a fait l'objet d'une directive #define
(même vide)
JCG
17/21
ESIEE
IN3T01
Abrégé de langage C
2010/2011
5 La bibliothèque standard du langage C
À chaque fichier accédé par un programme est associé un ensemble de tampons
d'entrée-sortie. Le couple fichier-tampon est un flux (stream), désignée par un pointeur sur le
type FILE, prédéfini dans stdio.h, qui définit également les trois pointeurs sur les flux
généralement ouverts : stdin, stdout et stderr (entrée, sortie et sortie erreur standard),
la constante NULL (absence de flux) et EOF (utilisée comme résultat lors de la fin de fichier).
5.1
La fonction printf
int printf ("format", expr1, expr2, ....)
Précise un format (sous forme de chaîne de caractères) pour les données en sortie. Les
éléments de la chaîne formats qui ne sont pas précédés de % sont sortis tels quels. Les
formats disponibles sont les suivants :
format
%c
%d
%f
%o
%s
%u
%x
%%
affichage sous forme
caractère
entier décimal
flottant
entier octal
chaîne de caractères
entier non signé
entier hexadécimal
le caractère %
Tableau 11 : formats de printf
Si # est un des formats ci-dessus,
format
affichage sous forme
%l#
type long
%-#
cadrage à gauche
%3#f
sur au moins trois positions
%.12#
• pour un entier, le nombre de
chiffres à afficher (ici 12)
• pour un réel, le nombre de chiffres
de la partie décimale à afficher
(avec arrondi)
• pour une chaînes, le nombre
maximum de caractères à afficher.
Tableau 12 : préfixes des formats de printf
5.2
La fonction scanf
int scanf("format",adr_var1, adr_var2, ....)
JCG
18/21
ESIEE
IN3T01
Abrégé de langage C
2010/2011
correspond à printf, mais pour les entrées. En plus, le préfixe de format * permet
d'ignorer un champ d'entrée.
Par exemple,
int i;
float x;
char nom[50];
scanf("%d %f %s', &i, &x, nom);
/* l'entrée 25 54.32e-1 Thompson
affectera 25 à i, 5.432 à x et "Thompson" à nom */
scanf(%2d %f %*d %2s", &i, &x, nom);
/* l'entrée 56789 0123 45a72 affectera 56 à i,
789.0 à x, ignorera 0123, "45" à nom. Le prochain
caractère lu sera 'a' */
JCG
19/21
ESIEE
IN3T01
Abrégé de langage C
2010/2011
Index des tableaux
Tableau 1 : les mots réservés du C..............................................................................................4
Tableau 2 : les constantes caractères spéciales...........................................................................5
Tableau 3 : les opérateurs arithmétiques.....................................................................................6
Tableau 4 : les comparateurs arithmétiques................................................................................6
Tableau 5 : les opérateurs d'égalité.............................................................................................6
Tableau 6 : les opérateurs de décalage........................................................................................7
Tableau 7 : les opérateurs bit à bit..............................................................................................7
Tableau 8 : les opérateurs logiques.............................................................................................7
Tableau 9 : les opérateurs unaires...............................................................................................8
Tableau 10 : priorités des opérateurs..........................................................................................9
Tableau 11 : formats de printf...................................................................................................18
Tableau 12 : préfixes des formats de printf...............................................................................19
Table des matières
1 La syntaxe C....................................................................................................4
1.1 Les règles d'écriture..........................................................................4
1.1.1 Commentaires et espaces...................................................4
1.1.2 Les identificateurs..............................................................4
1.1.3 Les types simples...............................................................4
1.1.4 Les constantes....................................................................5
1.1.5 Les variables......................................................................6
1.2 Les expressions et les opérateurs......................................................6
1.2.1 Les opérateurs arithmétiques.............................................6
1.2.2 Les opérateurs relationnels................................................6
1.2.3 Les opérateur d'égalité et d'inégalité..................................6
1.2.4 Les opérateurs de décalage................................................6
1.2.5 Les opérateurs bit à bit.......................................................7
1.2.6 Les opérateurs logiques.....................................................7
1.2.7 L'opérateur virgule ............................................................7
1.2.8 Les opérateurs d'affectation...............................................7
1.2.9 L'opérateur conditionnel....................................................7
1.2.10 Les opérateurs unaires.....................................................8
1.2.11 La conversion de type......................................................8
1.2.12 Priorité et ordre d'évaluation............................................8
2 Le contrôle du programme..............................................................................9
2.1 Les instructions de contrôle..............................................................9
2.1.1 L'instruction if....................................................................9
2.1.2 L'instruction switch............................................................9
2.1.3 Les itérations ...................................................................10
2.2 Les fonctions...................................................................................10
JCG
20/21
ESIEE
IN3T01
Abrégé de langage C
2010/2011
3 Les types composés et les pointeurs .............................................................12
3.1 Les tableaux....................................................................................12
3.2 Les pointeurs...................................................................................12
3.2.1 Définition.........................................................................12
3.2.2 Opérations........................................................................12
3.2.3 Pointeurs et tableaux .......................................................14
3.2.4 Arithmétique sur les pointeurs.........................................14
3.2.5 Exemples de fonctions.....................................................14
3.2.6 Allocation dynamique de mémoire..................................15
3.3 Structures et unions.........................................................................15
4 Le préprocesseur C........................................................................................17
4.1 Constantes et macros......................................................................17
4.2 Inclusion de fichier.........................................................................17
4.3 Compilation conditionnelle............................................................18
5 La bibliothèque standard du langage C.........................................................18
5.1 La fonction printf............................................................................18
5.2 La fonction scanf............................................................................19
JCG
21/21