156 votes

Que se passe-t-il pour une variable déclarée mais non initialisée en C ? A-t-elle une valeur ?

Si en C j'écris :

int num;

Avant d'assigner quoi que ce soit à num, la valeur de num est-elle indéterminée ?

4 votes

Euh, n'est-ce pas une variable définie, pas une variable déclarée? (Désolé si c'est mon C++ qui brille à travers...)

8 votes

Non. Je peux déclarer une variable sans la définir: extern int x; Cependant, la définition implique toujours la déclaration. Ce n'est pas vrai en C++, avec les variables membres de classe statiques on peut définir sans déclarer, car la déclaration doit être dans la définition de la classe (pas la déclaration!) et la définition doit être en dehors de la définition de la classe.

0 votes

ee.hawaii.edu/~tep/EE160/Book/chap14/subsection2.1.1.4.html Il semblerait que "défini" signifie que vous devez également l'initialiser.

210voto

bdonlan Points 90068

Les variables statiques (portée de fichier et statiques de fonction) sont initialisées à zéro :

int x; // zéro
int y = 0; // également zéro

void foo() {
    static int x; // également zéro
}

Les variables non statiques (variables locales) sont indéterminées. Les lire avant de leur attribuer une valeur entraîne un comportement indéfini.

void foo() {
    int x;
    printf("%d", x); // le compilateur est libre de planter ici
}

En pratique, elles tendent juste à avoir une valeur absurde au départ - certains compilateurs peuvent même mettre des valeurs spécifiques et fixes pour rendre cela évident lors de l'inspection en débogueur - mais strcitement parlant, le compilateur est libre de faire n'importe quoi, allant du plantage à l'invocation de démons par vos narines.

Quant à savoir pourquoi il s'agit d'un comportement indéfini au lieu simplement d'une "valeur indéterminée/arbitraire", il existe un certain nombre d'architectures de processeurs qui possèdent des bits de drapeau supplémentaires dans leur représentation pour divers types. Un exemple moderne serait l'Itanium, qui possède un bit "Pas une chose" dans ses registres l'Itanium, qui possède un bit "Pas une chose" dans ses registres; bien sûr, les rédacteurs de la norme C considéraient des architectures plus anciennes.

Essayer de travailler avec une valeur avec ces bits de drapeau peut entraîner une exception du CPU dans une opération qui ne devrait vraiment pas échouer (par exemple, l'addition d'entiers, ou l'affectation à une autre variable). Et si vous laissez une variable non initialisée, le compilateur pourrait récupérer certains déchets aléatoires ayant ces bits de drapeau - ce qui signifie que toucher cette variable non initialisée peut être mortel.

3 votes

Oh non, ils ne le sont pas. Ils pourraient l'être, en mode de débogage, lorsque vous n'êtes pas devant un client, pendant les mois avec un "R", si vous avez de la chance

8 votes

Qu'est-ce qui ne va pas? L'initialisation statique est requise par la norme; voir ISO/IEC 9899:1999 6.7.8 #10

3 votes

Le premier exemple est bien autant que je puisse le dire. Je suis moins sûr de la raison pour laquelle le compilateur pourrait planter dans le deuxième cas cependant :)

61voto

DigitalRoss Points 80400

0 si statique ou global, indéterminé si la classe de stockage est automatique

C a toujours été très précis sur les valeurs initiales des objets. S'ils sont globaux ou static, ils seront mis à zéro. Si auto, la valeur est indéterminée.

C'était le cas dans les compilateurs pré-C89 et cela a été spécifié par K&R et dans le rapport original de C de DMR.

C'était le cas en C89, voir la section 6.5.7 Initialisation.

Si un objet qui a une durée de stockage automatique n'est pas initialisé explicitement, sa valeur est indéterminée. Si un objet qui a une durée de stockage statique n'est pas initialisé explicitement, il est initialisé implicitement comme si chaque membre de type arithmétique était affecté à 0 et que chaque membre de type pointeur était affecté à une constante pointeur nulle.

C'était le cas en C99, voir la section 6.7.8 Initialisation.

Si un objet qui a une durée de stockage automatique n'est pas initialisé explicitement, sa valeur est indéterminée. Si un objet qui a une durée de stockage statique n'est pas initialisé explicitement, alors :
— s'il a un type pointeur, il est initialisé à un pointeur nul ;
— s'il a un type arithmétique, il est initialisé à zéro (positif ou non signé) ;
— s'il s'agit d'un agrégat, chaque membre est initialisé (de manière récursive) selon ces règles ;
— s'il s'agit d'une union, le premier membre nommé est initialisé (de manière récursive) selon ces règles.

Quant à ce que signifie exactement indéterminé, je ne suis pas sûr pour C89, C99 dit :

3.17.2
valeur indéterminée

soit une valeur non spécifiée, soit une représentation de piège

Mais quelle que soit l'opinion des standards, dans la vie réelle, chaque page de la pile commence en réalité à zéro, mais lorsque votre programme regarde les valeurs de la classe de stockage auto, il voit ce qui a été laissé derrière par votre propre programme lorsqu'il a utilisé ces adresses de pile pour la dernière fois. Si vous allouez beaucoup de tableaux auto, vous les verrez finalement commencer proprement par des zéros.

Vous vous demandez peut-être, pourquoi est-ce ainsi ? Une réponse SO différente traite de cette question, voir : https://stackoverflow.com/a/2091505/140740

3 votes

Indéterminé habituellement signifie qu'il peut faire n'importe quoi. Il peut être zéro, il peut être la valeur qui était là, il peut planter le programme, il peut faire en sorte que l'ordinateur produise des pancakes aux myrtilles par le lecteur CD. vous n'avez absolument aucune garantie. Cela pourrait causer la destruction de la planète. Du moins en ce qui concerne la spécification... quelqu'un qui aurait fait un compilateur qui ferait réellement quelque chose de ce genre serait très mal vu B-)

0 votes

Dans le brouillon C11 N1570, la définition de valeur indéterminée peut être trouvée à la section 3.19.2.

1 votes

Est-ce donc toujours dépendant du compilateur ou du système d'exploitation de définir la valeur d'une variable statique ? Par exemple, si je crée mon propre système d'exploitation ou mon propre compilateur, et que je définis également une valeur indéterminée par défaut pour les variables statiques, est-ce possible ?

14voto

AndreyT Points 139512

Il dépend de la durée de stockage de la variable. Une variable avec une durée de stockage statique est toujours implicitement initialisée à zéro.

Quant aux variables automatiques (locales), une variable non initialisée a une valeur indéterminée. Une valeur indéterminée signifie entre autres que quelle que soit la "valeur" que vous pourriez "voir" dans cette variable, elle n'est pas seulement imprévisible, elle n'est même pas garantie d'être stable. Par exemple, en pratique (c'est-à-dire en ignorant l'UB pendant une seconde), ce code

int num;
int a = num;
int b = num;

ne garantit pas que les variables a et b recevront des valeurs identiques. Fait intéressant, il ne s'agit pas d'un concept théorique pointilleux, cela se produit couramment en pratique en tant que conséquence de l'optimisation.

En général, la réponse populaire selon laquelle "elle est initialisée avec n'importe quelle valeur résiduelle se trouvant en mémoire" n'est même pas proche de la réalité. Le comportement d'une variable non initialisée est différent de celui d'une variable initialisée avec des valeurs résiduelles.

0 votes

Je ne comprends pas (enfin je peux très bien comprendre) pourquoi celui-ci a beaucoup moins de votes que celui de DigitalRoss juste une minute après :D

6voto

Lawrence Dol Points 27976

La valeur est indéfinie (ou indéterminée pour utiliser un autre mot anglais avec le même sens sémantique dans ce contexte); elle pourrait simplement être ce qui était précédemment dans l'emplacement mémoire.

3voto

Jerry Coffin Points 237758

Cela dépend. Si cette définition est globale (en dehors de toute fonction) alors num sera initialisé à zéro. Si elle est locale (à l'intérieur d'une fonction) alors sa valeur est indéterminée. En théorie, même tenter de lire la valeur a un comportement indéfini - C permet la possibilité de bits qui ne contribuent pas à la valeur, mais qui doivent être définis de certaines manières pour obtenir des résultats définis de la lecture de la variable.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X