Bloc 2Langage C : bases

Langage C : bases

Éléments du language

Caractères permis

  • lettres de l’alphabet
  • chiffres
  • caractères spĂ©ciaux
  • sĂ©parateurs de mots (permis mais ignorĂ©s par le compilateur)

Commentaires

Balise ouvrante : /*

#include <stdio.h>
/* début
du
programme */
int main() {
	printf("Hello world\n");
	exit();
}

Balise par ligne : //

#include <stdio.h>
// début
// du
// programme
int main(){
	printf("Hello world\n");
	exit(0);
}

Les mots réservés

autodoubleintstruct
breakelselongswitch
caseenumregistertypedef
charexternreturnunion
constfloatshortunsigned
continueforsignedvoid
defaultgotosizeofvolatile
doifstaticwhile

Les types de base

Les types de base

Les types entiers

Les types entiers
  • sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) OĂą l’opĂ©rateur sizeof retourne la taille en bytes de son paramètre: type ou variable.

Les types réels

Le langage C (ANSI C) connaît 3 types réels : float, double et long double.

Le pseudo-type booléen

Pour des raisons de lisibilité du code, nous utiliserons dans ce cours le fichier d’en-tête stdbool.h de la bibliothèque standard C. Introduit avec la norme C99, ce fichier définit différentes macros, dont un type booléen bool et deux valeurs, true qui équivaut à 1 et false qui équivaut à 0.

Opérateurs

Opérateurs

Les conversions de types

Conversions explicites par cast

Le cast (ou transtypage explicite) d’une expression permet de changer le type de la valeur renvoyée par l’évaluation de cette expression.

Conversions explicites
int a = 10;
float b = (float)a; // Conversion explicite d'un int en float

Conversions implicites

Par ailleurs, C convertit automatiquement certaines expressions dans un type préférentiel, lors de leur évaluation

Les conversions unaires vont s’appliquer à un seul opérande, en respectant les règles énoncées dans le tableau suivant :

Conversions unaires

Les conversions binaires vont s’appliquer sur un des opérandes, en respectant la hiérarchie des types suivantes :

int < long < float < double < long double

Les conversions d’affectation permettent à l’opérande de droite d’être converti pour rester compatible avec le type de l’opérande de gauche. En fonction de la priorité des opérateurs, nous rencontrons les conversions suivantes :

Conversions d'affectation

Déclaration et définition d’une variable

C distingue déclaration et définition de variables et de fonctions. Une déclaration indique simplement au compilateur l’existence d’un élément dont le nom et le type ont été spécifiés. Il n’y a pas de réservation de mémoire et l’élément ne peut pas encore être utilisé. Par contre lors d’une définition de variable ou de fonction, il y a physiquement réservation d’espace mémoire (pour y stocker une valeur ou pour donner le code de la fonction). Nous reviendrons plus tard sur cette distinction.

Une variable se déclare en spécifiant son type et l’identificateur qui la représente dans le programme, tandis que lorsqu’on définit une variable, il est possible de lui donner une valeur initiale. Par exemple :

int a;   /* déclaration ou définition de la variable a de type int */

Les déclarations et définitions multiples (plusieurs déclarations et définitions dans la même expression) sont permises.

int a, b, c = 5, d;   /* définition des variables de type int a, b, c, d où seule c est initialisée */

Rem : La valeur d’initialisation peut être le résultat d’une expression mais elle doit être connue lors de la compilation.

int taille = 3 * 4;

Les constantes

En ANSI C, il existe deux techniques pour définir une constante : soit en utilisant une macro (via la directive de préprocesseur #define)

#define MAX 10

Qui sera convertie en sa valeur lors de la pré-compilation,

soit en définissant une variable qualifiée de constante (via le mot réservé const):

const int MAX = 10;

Notez que, par convention, l’identificateur d’une constante sera toujours composé de lettres majuscules.

Les instructions simples

  • Le C accepte l’usage de l’instruction nulle (ou instruction vide), marquĂ©e par le caractère ’;’, le terminateur d’instructions.

    ;    /* instruction nulle */
  • Il permet Ă©galement l’utilisation de l’instruction-expression, qui Ă©value l’expression pour ses effets de bord.

    20 + 2*b;    /* instruction sans effet de bord: évaluation puis oubli du résultat */

    Nous rencontrerons essentiellement trois cas d’utilisation :

    • Les affectations

      a = b * c;
    • Les prĂ© ou post incrĂ©mentations et dĂ©crĂ©mentations

      a++; a--; ++a; --a;
    • Et les appels de fonction de type void ou dont la valeur de retour n’est pas exploitĂ©e

      printf(...);
  • break : instruction qui permet de quitter une branche du switch ou de sortir d’une rĂ©pĂ©titive directement, sans réévaluer la condition.

  • continue : instruction utilisĂ©e uniquement dans les rĂ©pĂ©titives, elle permet de sauter la suite du corps de la rĂ©pĂ©titive et de passer directement Ă  une nouvelle vĂ©rification de la condition; dans un for, elle permet l’exĂ©cution de l’adaptation.

Le bloc d’instructions

Lorsque plusieurs instructions doivent être traitées conjointement, elles sont regroupées en un bloc d’instructions encadrés par une paire d’accolades ' et '.

{
	// instr1
	// instr2
}

Du point de vue de la syntaxe, un bloc se comporte comme une instruction unique et peut figurer en tout endroit où une instruction simple est permise. Il n’est pas suivi par le ’;’ car les accolades servent de délimiteurs.

Un bloc d’instructions peut débuter par la définition d’un certain nombres de variables, locales à ce bloc d’instructions (i.e. leur existence se termine à la fin du bloc).

{
	// définition de variables
	// liste d'instructions
}

Si un identificateur redéfinit un variable déjà existante, la nouvelle variable occulte l’ancienne, définie dans un bloc englobant. Dans l’exemple suivant :

{
	int i = 5;
	{
		int i = 7;
		printf("i vaut %d\n", i++);
	}
	printf("i vaut %d\n", i);
}

l’affichage donnera:

i vaut 7
i vaut 5

Les répétitives

Il y a différents type de répétitives: le while, le for et le do … while. Toutes ces répétitives utilisent une condition de continuation, c-à-d que l’itération suivante est réalisée si la condition testée vaut VRAI. En d’autres mots, la boucle se termine lorsque la condition devient FAUX.

while

La condition est vérifiée avant d’entamer l’itération et donc si la condition est directement FAUX, l’instruction n’est pas exécutée.

while (cdt){
	// instruction(s)
}

for

Le for est une écriture condensée du while. Il est constitué de 3 parties : l’initialisation, la condition et l’adaptation.

{
	for (int i = 0; i < 10; i++)
	{
		// variable i utilisable uniquement dans la boucle for
	}
	// variable i inexistante
}
{
	int i;
	for (i = 0; i < 10; i++)
	{
		// variable i utilisable
	}
	// variable i utilisable
}
// variable i inexistante

Les alternatives

C connaît deux types de traitements conditionnels: les alternatives, qui permettent de réaliser ou pas un traitement en fonction d’une condition, et les switch, qui réalisent un traitement en fonction du contenu d’une variable dénombrable (entière).

if

if (cdt){
	// instruction
}

et les if…else

if (cdt) {
	// instruction1
}
else {
	// instruction 2
}

switch

Le switch peut être considéré comme un branchement multiple en fonction d’une valeur entière. Dès que l’on est aiguillé vers une branche, le traitement se poursuit en séquence. Cela signifie que toutes les instructions qui suivent le case sont exécutées, jusqu’à la fin du bloc ou jusqu’à une instruction de rupture break qui permet de quitter la structure de contrôle.

switch (exp) {
	case val1:
	case val2:
		... // instructions exécutées si exp = val1 ou val2
		break;
	case val3:
		... // instructions executée si exp = val3
	case val4:
		... // instruction executée si exp = val4 ou val3
		break;
	default:
		... // instruction executée si exp <> val1, val2, val3 et val 4
}
switch (exp) {
	case val1:
		// instruction1
		break;
	case val2:
		// instruction2
		break;
	case val3:
		// instruction3
		break;
	default:
		// instruction 4
}

est l’equivalent d’un if imbriqué:

if (exp == val1){
	// instruction1
} else if (exp == val2){
	// instruction2
} else if (exp == val3){
	// instruction3
} else {
	// instruction 4
}