Si en C j'écris :
int num;
Avant d'assigner quoi que ce soit à num
, la valeur de num
est-elle indéterminée ?
Si en C j'écris :
int num;
Avant d'assigner quoi que ce soit à num
, la valeur de num
est-elle indéterminée ?
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.
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
Qu'est-ce qui ne va pas? L'initialisation statique est requise par la norme; voir ISO/IEC 9899:1999 6.7.8 #10
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 :)
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
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-)
Dans le brouillon C11 N1570, la définition de valeur indéterminée
peut être trouvée à la section 3.19.2.
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 ?
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.
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 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.
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.