Rappel de C - la syntaxe

par Tom
le 08/01/2020

Sommaire


Temps de lecture estimé : 45min-1h


Avertissement

Le C est sensible à la casse : Truc, truc et TRUC sont trois mots différents.

Le code suivant ne compile pas :

int truc = 5;
printf("%d", TrUc);

Identificateurs

= peut être utilisé pour nommer quelque chose (variable, fonction, structure, ...)

Peut contenir des lettres (A-Z, a-z), des chiffres (0-9) et des tirets bas (_) mais ne peut pas commencer par un chiffre.


Nombres

Entiers

Type : int

Notation décimale : 1, 41, 123

Notation hexadécimale : 0x1, 0xA0

Notation octale : 0777, 0123

Flottants

Type : float, double

Se note avec un point : 41.123, 0.123.

Notation scientifique : 3e-8 = $3*10^{-8}$.

Attention : les types float et double ne sont pas interchangeables directement. Les litéraux float doivent se terminer par un f.

Le type double est un surensemble du type float, donc une valeur float peut être utilisée dans un double mais pas l'inverse.

Exemples :

  • 2.5 est un double
  • 2.5f est un float

Booléens

Contrairement au Java, le C ne possède pas de type booléen natif, on utilise le plus souvent des nombres ordinaires.

Ainsi, la valeur 0 correspond à "faux" et toute autre valeur correspond à "vrai".


Caractères

Type : char

Se note entre guillemets simples: 'A', 'a', ' '.

Caractères spéciaux :

  • '\n' : saut de ligne
  • '\t' : tabulation

Chaînes de caractères

Le C ne possède pas de type "chaîne de caractère", on utilise à cet effet des tableaux de caractères.

Ils sont notés char[] ou char*, éventuellement const :

const char* maChaine = "Bonjour tout le monde";

Les chaînes se notent entre guillemets doubles : "abc", "Bonjour".

Utilisation possible des caractères spéciaux dans une chaîne :

"Bonjour\nAu revoir"

Donne :

Bonjour
Au revoir

Attention : pour comparer deux chaînes, il faut utiliser strcmp(.., ..) et pas == :

const char* a = "abc";
const char* b = "abc";

if (a == b) // INCORRECT
{ 
    ...
}

if (!strcmp(a, b)) // CORRECT
{ 
    ...
}

(on reviendra plus tard sur strcmp)


Commentaires

Un commentaire est un bout de code qui sert à mettre des infos supplémentaires dans le code à destination des humains qui vont le lire.

Les commentaires sont ignorés par le compilateur.

Il en existe 2 types :

  • commentaires sur une ligne : // commentaire
  • commentaires sur plusieurs lignes :
    /* début
    bonjour
    au revoir
    */ fin

Variables

Syntaxe : type nom; ou type nom = valeur;type est le type et nom le nom.

Exemples :

  • int a; déclare une variable a de type int (nombre entier).
  • int* a; déclare une variable a de type int* (pointeur vers un nombre entier).
  • double b = 2.5; déclare et initialise une variable b de type double (flottant double-précision) avec la valeur 2,5.

Déclarer c'est dire "la variable existe".

Initialiser c'est affecter la valeur à la variable.

Attention : une variable non initialisée peut contenir n'importe quelle valeur. int x; ne dit absolument rien sur ce que contient x, il ne faut pas donc pas lire dedans.


Tableaux

On déclare un tableau en mettant [N] après le nom, où N est le nombre d'éléments (fixe).

Exemples :

  • int a[10]; : a est un tableau de 10 entiers
  • float b[5]; : b est un tableau de 5 flottants

On accède à l'élément N (en partant de 0) d'un tableau avec l'opérateur [] :

  • a[5] est le sixième élément de a
  • a[8] = 123; met 123 dans le neuvième élément de a

On peut déclarer un tableau à plus d'une dimension en mettant plusieurs [] :

int maMatrice[5][3];

Le code ci-dessus crée une matrice 2D de 5 par 3, où chaque case est un entier.

Attention : comme les variables normales, les tableaux ne sont pas initialisés par défaut à l'inverse du Java où ils sont remplis de zéros. Il ne faut jamais lire dans une variable non initialisée.


Fonctions

Syntaxe :

type nom(paramètre, paramètre, ...) 
{
    ...
}

type est le type de retour de la fonction (ce que la fonction renvoie). Si la fonction ne renvoie rien (c'est alors une procédure), on écrit void ; nom est le nom de la fonction, et paramètre = type nom (cf Variables).

Dans une fonction qui renvoie une valeur, on écrit return valeur; pour renvoyer une valeur. Cette valeur peut être un litéral (un nombre, une chaîne), une variable, ou un appel à une autre fonction.

Dans une fonction ne renvoyant pas de valeur, on peut écrire return;.

Dans les deux cas, tout code se trouvant après le return ne sera pas exécuté (sauf cas rares, on verra ça plus tard).

Exemple :

int nombreAuCarre(int leNombre) 
{
    return leNombre * leNombre; // met leNombre au carré et renvoie le résultat

    int b = 123; // incorrect, car il y a un return plus haut donc la ligne ne serait jamais atteinte
}

.
.
.

int resultat = nombreAuCarre(7);
// resultat contient maintenant 49

Autre exemple :

int main() 
{
    puts("bonjour");
}

Opérateurs

Arithmétique

  • a + b : addition
  • a - b : soustraction
  • a * b : multiplication
  • a / b : division
    • Attention : si a et b sont entiers, alors le résultat sera entier
    • 3 / 2 vaut 1 car le 1.5 est tronqué à l'entier inférieur.
    • Pour avoir le bon résultat, il faudrait faire 3.0 / 2 par exemple.
  • a % b : reste de la division euclidienne
    • a % 2 donne la parité de a (0 si pair, 1 si impair)
    • a % b == 0 équivaut à "a est divisible par b"
  • -a : négation

Logique

  • a && b : conjonction (a ET b), vrai si les deux sont vrais
  • a || b : disjonction (a OU b), vrai si au moins un des deux est vrai
  • !a : négation : vrai si a est faux

Comparaison

  • a == b : égal À NE PAS UTILISER POUR LES CHAÎNES !
  • a != b : différent
  • a > b : strictement supérieur
  • a >= b : supérieur ou égal
  • a < b : strictement inférieur
  • a <= b : inférieur ou égal

Binaire (bit-à-bit)

  • a & b : ET binaire (les deux sont vrais)
  • a | b : OU binaire (au moins un des deux est vrai)
  • a ^ b : OU exclusif binaire (exactement un des deux est vrai)
a b ET OU OU excl
0 0 0 0 0
0 1 0 1 1
1 0 0 1 1
1 1 1 1 0

Typedef (début)

En C, il est possible de créer des "raccourcis" de types, par exemple si on se sert souvent d'un type tableau en particulier.

Exemple : vous écrivez un programme qui traite des matrices 3x3 et vous avez donc beaucoup de fonctions prenant de telles matrices en entrée.

int fonc1(int matrice[3][3])
{
    ...
}

etc. Au lieu de devoir taper int ...[3][3] à chaque fois, on préfère faire :

typedef int MAT[3][3];

Cette ligne "crée" un raccourci appelé "MAT" qui représente une matrice 3x3 d'entiers.

On peut donc réécrire la fonction :

int fonc1(MAT matrice)
{
    ...
}

Sur le long terme, ça peut faire économiser beaucoup de code. La syntaxe formelle est :

typedef type nomRaccourci;

Ça se déclare pour ainsi dire comme les variables, excepté qu'au lieu de créer une variable on crée un raccourci.

Suite dans la page sur les blocs.

Blocs

Voir l'article complet sur les blocs.