Erreurs et concepts clés en langage C

Définition des tableaux unidimensionnels

Dans la déclaration d'un tableau à une dimension type nom_tableau[longueur], le type désigne le type des éléments individuels du tableau, et non le type de la variable tableau elle-même. Par exemple, dans int a[10];, int indique que chaque élément (a[0], a[1], ..., a[9]) est de type entier. Le type complet de la variable tableau est déterminé par le type des éléments et la longueur, soit int[10].

Déclaration Sens du type (type élémentaire) Type réel de la variable tableau
float scores[30]; float float[30]
char nom[20]; char char[20]

Cette confusion vient du fait que les tableaux sont des structures composites regroupant plusieurs éléments de même type, contrairement aux variables simples.

Constantes de caractères et séquences d'échappement

La constante de caractère '\08' est invalide. En pratique, le compilateur la traite comme '\0' suivi de '8', générant une erreur de type multi-character constant. Voici une illustration :

#include <stdio.h>

int main() {
    char chaine[] = "\08";
    printf("Taille : %zu\n", sizeof(chaine));  // Sortie : 3 (incluant '\0')
    printf("Premier : %d\n", chaine[0]);        // Sortie : 0 (code ASCII de '\0')
    printf("Second : %c\n", chaine[1]);          // Sortie : '8'
    return 0;
}

Initialisation des tableaux et sizeof

Lors de l'initialisation d'un tableau, la taille peut être omise seulement pour la première dimension dans les tableaux multidimensionnels. Par exemple :

int tableau[][3] = { {1,2,3}, {4,5,6} }; // Lignes déduites automatiquement

L'opérateur sizeof sur un tableau dans son portée de définition retourne la taille totale en octets. Si le tableau est passé en paramètre de fonction, il dégénère en pointeur, et sizeof retourne la taille du pointeur.

Priorité des opérateurs et expressions

L'opérateur ternaire ? : est associatif à droite. L'expression a < b ? a : b > c ? b : c est équivalente à a < b ? a : (b > c ? b : c). De plus, sizeof ne calcule pas la valeur de l'expression à l'intérieur, et l'opérateur virgule retourne la valeur la plus à droite. La conversion de type implicite s'applique entre les branches du ternaire.

Pour compter les bits à 1 dans un entier :

int x, compteur = 0;
scanf("%d", &x);
while (x) {
    compteur++;
    x = x & (x - 1);
}

Boucles et flux de contrôle

Les instructions break et continue fonctionnent différemment dans les boucles et les switch. break sort du switch ou de la boucle, tandis que continue passe à l'itération siuvante de la boucle. Si switch est hors d'une boucle, continue provoque une erreur de compilation.

Un piège courant avec while est l'absence d'incrémentation, menant à une boucle infinie :

int i = 1;
while (i <= 10) {
    printf("%d\n", i);
    // i non incrémenté : boucle infinie
}

Fonctions et passage de paramètres

Les fonctions peuvent avoir des paramètres variables, comme printf. Lors du passage d'un tableau en paramètre, il devient un pointeur, et sizeof retourne la taille du pointeur, non du tableau. Les paramètres formels reçoivent des copies des arguments (passage par valeur), donc les modifications locales n'affectent pas les variables originales.

Exemple de déclaration incorrecte : void income(double number), expend(double number);expend est implicitement de type int si non spécifié, mais en réalité, les fonctions sans type explicite sont par défaut int en C ancien.

Gestion de la mémoire et stockage des constantes

Les constantes comme 10 dans int a = 10; sont généralement intégrées directement dans les instructions (code segment) et ne prennent pas de mémoire supplémentaire. Les constantes globales ou statiques peuvent être stockées dans la section de données en lecture seule (.rodata). La pile est allouée à partir d'adresses hautes, et les variables locales sont stockées dessus.

En IEEE 754, le dépassement de capacité (overflow) des flottants est principalement dû à un dépassement de l'exposant (exponent overflow), tandis que le sous-découlement (underflow) se produit lorsque la valeur est trop petite pour être représentée, même avec des nombres dénormalisés.

Autres pièges courants

Les opérations sur les bits, comme l'inversion et l'addition d'un, peuvant être utilisées pour l'arithmétique saturation. Les types char sont par défaut signés, tandis que unsigned char est non signé. La précision de double est supérieure à celle de float, avec une plus grande plage de valeurs.

// Conversion implicite dans un ternaire
double n;
sizeof(n > 0 ? 1 : -1.f) == sizeof(double);

Étiquettes: C-langage tableaux sizeof opérateurs fonctions

Publié le 25 juin à 03h33