Langage C
Langage C
Langage C
HABIB NDIAYE
INGÉNIEUR DÉVELOPPEUR
+221 77 319 94 76 /
habibndiaye08@gmail.com
PLAN
Il est possible de faire une traduction du langage de haut niveau vers celui de bas
niveau, avec un traducteur. On distingue alors deux types de traducteurs :
- l’interpréteur : il traduit le programme instruction par instruction.
- le compilateur : il traduit le programme dans son ensemble.
Le langage C a été créé en 1978 par Brian W. Kernighan et Denis Ritchie au sein des
laboratoires Bell, avec pour objectif de créer un système d’exploitation (une
réécriture de UNIX). Face à sa popularité grandissante, il a été normalisé en 1989
par le NIST. De nombreux autres langages comme Java, JavaScript ou C# ont
largement repris la syntaxe du C, mais sans être compatibles.
Le langage C est un langage de haut niveau( on dit parfois aussi qu’il est le plus bas
des langages de haut niveau!!!), impératif, compilé, typé et déclaratif.
Avantages
- Grande notoriété et très utilisé ; donc possibilité d’avoir de la documentation et
/ou de l’aide ;
- Certain nombre de fonctions prédéfinies dans des bibliothèques ;
- Langage portable et standardisé ;
- Simplicité ;
- Gestion de la mémoire ;
- Vitesse d’exécution.
Inconvénients
- Rigueur d’écriture ;
- Définition de certains concepts par soi-même .
LANGAGE C : HISTORIQUE & CARACTERISTIQUES
Etapes de la compilation en C
- les identificateurs,
- les mots-clés,
- 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.
Bases du langage C
Les identificateurs
Il existe une série de mots réservés (aussi appelés mots-clés) au langage C, c’est-à-
dire qu’on ne peut pas les utiliser comme identificateurs ( de variables, de fonctions
ou de nouveaux types). Ils sont au nombre de 32 :
Bases du langage C
Les commentaires
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.
Règles d’écriture des identificateurs (noms) des variables :
- ils peuvent contenir des lettres, des chiffres et le caractère ;
- ils ne doivent pas commencer par un chiffre;
- les accents sont interdits;
- il sont sensibles à la casse : par exemple, la variable prix est différent de la
variable PRIX;
Les types prédéfinis
Le type caractère
Par exemple
Le type char a une particularité : en effet, on considère qu’une donnée de type char
n’est rien d’autre qu’un entier codé sur un octet. Et donc tout objet de type char
peut être utilisé dans une expression qui utilise des objets de type entier. Par
exemple, si une variable c est de type char, l’expression c + 1 sera correcte.
Les types prédéfinis
Le type caractère
Pour déclarer une variable de type entier, on utilise le mot-clé int. Le type entier se
définit de plusieurs manières :
- en précisant est-ce que c’est un entier signé (mot-clé signed) ou non-signé
(mot-clé unsigned). Le bit de poids fort de l’entier correspond au signe (0 pour
positif, 1 pour négatif). Par défaut, les entiers sont signés.
- et/ou en précisant l’intervalle de valeurs avec les mots-clés : short ou long. (il
existe aussi long long sur certains compilateurs)
Le tableau ci-dessous résume les types entiers.
Les types prédéfinis
Le type entier
Remarques
- Le plus souvent, on utilisera juste int pour déclarer une variable de type entier.
- Les spécifications pour le type entier sont définies dans la librairie limits.h.
- Les intervalles des entiers dépendent du système d’exploitation, du compilateur
et/ou du processeur utilisé.
Les types prédéfinis
Le type réel
Les flottants (les réels) sont désignés par les mot-clés float, double et long
double.
Remarques
- Pour les flottants, pas besoin d’utiliser les mots-clés signed et unsigned.
- Le plus souvent, on utilisera juste float pour déclarer une variable de type
flottant.
- Pour les nombres à virgule, le point remplace la virgule.
Les types prédéfinis
Le type void
Il existe un type spécial, appelé void, qui exprime l’idée de ”aucune valeur” ou
”vide”. On l’utilise par exemple :
- comme type de retour d’une fonction ne retournant pas de valeur;
- dans le prototype de fonctions sans paramètres;
- pour déclarer un pointeur générique.
NB :
Le type booléen n’existe pas explicitement en C.
Il est plutôt défini par le langage C++ (type bool). Dans la pratique, si on veut
définir une variable booléenne en C, on passera par le type int : 0 pour false, 1
pour true.
Les opérateurs
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 ;
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.
Les opérateurs
Opérateurs arithmétiques
- 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.
Les opérateurs
Opérateurs relationnels
&& Et logique
|| Ou logique
! Négation logique
Comme pour les opérateurs de comparaison, la valeur retournée par ces
opérateurs est un int qui vaut 1 si la condition est vraie et 0 sinon.
Les conversions de types (ou casts) permettent de passer d’un type de base `a un
autre type de base. La conversion peut être :
- implicite : elle est alors effectuée directement par le compilateur. Par exemple, la
somme d’une variable de type float et d’une autre de type int sera
automatiquement de type float; pas besoin donc de le signaler au compilateur.
- explicite : en utilisant la syntaxe suivante : (unType) objet; où objet peut être un
nom de variable ou une expression à convertir dans le type unType.
Les fonctions d’entrées-sorties classiques
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 :
La fonction scanf permet de saisir des données au clavier et de les stocker aux
adresses spécifiées par les arguments de la fonctions.
On indique le format dans lequel les données lues sont converties. Elle ne contient
pas d’autres caractères (notamment pas de \n). Comme pour printf, les
conversions de format sont spécifiées par un caractère précédé du signe %. Les
formats valides pour la fonction scanf diffèrent légèrement de ceux de la fonction
printf.
Les fonctions d’entrées-sorties classiques
La fonction de saisie scanf
Impression et lecture de caractères
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.
Les instructions
Les branchements conditionnels : if---else
Il peut arriver que l’on ne veuille effectuer le test de continuation qu’après avoir
exécuté l’instruction. Dans ce cas, on utilise la boucle do---while. Sa syntaxe est :
do {
instruction;
} while(expresion);
Ici, instruction sera exécutée tant que expression est non nulle. Cela signifie donc
que instruction est toujours exécutée au moins une fois.
- On ne met pas de blanc entre un opérateur unaire et son opérande, ni entre les
deux caractères d’un opérateur d’affectation composée.
- Les instructions doivent être indentées afin que toutes les instructions d’un
même bloc soient alignées.
Les structures de données
Les tableaux
Une structure est une suite finie d’objets de types différents. Contrairement aux
tableaux, les différents éléments d’une structure n’occupent pas nécessairement
des zones contigües en mémoire. Chaque élément de la structure, appelé membre
ou champ, est désigné par un identificateur.
On distingue la déclaration d’un modèle de structure de celle d’un objet de type
structure correspondant à un modèle donné. La déclaration d’un modèle de
structure dont l’identificateur est modele suit la syntaxe suivante :
Les énumérations permettent de définir un type par la liste des valeurs qu’il peut
prendre. Un objet de type énumération est défini par le mot-clé enum et un
identificateur de modèle, suivis de la liste des valeurs que peut prendre cet objet :
enum modele {constante-1, constante-2,...,constante-n};
En réalité, les objets de type enum sont représentés comme des int. Les valeurs
possibles constante-1, constante-2, ..., constante-n sont codées par des entiers
de 0 à n-1. Par exemple, le type enum booleen défini dans le programme suivant
associe l’entier 0 à la valeur faux et l’entier 1 à la valeur vrai.
Un pointeur est un objet dont la valeur est égale à l’adresse d’un autre objet. On
déclare un pointeur par l’instruction:
type *nom-du-pointeur;
En effet, pour un pointeur sur un objet de type char, la valeur donne l’adresse de
l’octet où cet objet est stocké. Par contre, pour un pointeur sur un objet de type
int, la valeur donne l’adresse du premier des 4 octets où l’objet est stocké. Dans
l’exemple suivant, on définit un pointeur p qui pointe vers un entier i :
int i = 3;
int *p;
p = &i;