Pourquoi certaines variables const se référant à certaines variables const exportées obtenir la valeur 0?

StackOverflow https://stackoverflow.com/questions/920615

Question

Considérez ce qui suit. J'ai deux constantes exportées comme suit:

// somefile.h
extern const double cMyConstDouble;
extern const double cMyConstDouble2;

et

// somefile.cpp
const double cMyConstDouble = 3.14;
const double cMyConstDouble2 = 2.5*cMyConstDouble;

Ces constantes sont maintenant référencées un autre endroit pour définir deux constantes statiques (localement visibles):

// someotherfile.cpp
#include "somefile.h"
static const double cAnotherDouble = 1.1*cMyConstDouble;
static const double cAnotherDouble2 = 1.1*cMyConstDouble2;
printf("cAnotherDouble = %g, cAnotherDouble2 = %g\n",
       cAnotherDouble, cAnotherDouble2);

Ce qui donne le résultat suivant:

cAnotherDouble = 3.454, cAnotherDouble2 = 0

Pourquoi le deuxième double 0? J'utilise .NET 2003 compilateur C (13.10.3077).

Était-ce utile?

La solution

Parce que cMyConstDouble est déclarée comme extern, le compilateur n'est pas en mesure d'assumer sa valeur et ne génère pas d'initialisation de compilation pour cMyConstDouble2. Comme le cMyConstDouble2 est compile pas le temps initialisé, l'ordre d'initialisation par rapport à cAnotherDouble2 est aléatoire (non défini). Voir initialisation statique fiasco pour plus informations.

Autres conseils

Je ne vais pas plonger mon orteil dans les questions de extern ici, mais pourquoi ne vous placez pas tout simplement les consts dans les fichiers d'en-tête appropriés et oublier « exporter » les utiliser extern? Voici comment consts sont censés être utilisés en C ++, et pourquoi ils ont une liaison interne.

En d'autres termes:

// someheader.h
const double cMyConstDouble = 3.14;
const double cMyConstDouble2 = 2.5*cMyConstDouble;

et #include ce fichier chaque fois que vous en avez besoin.

Ceci est dangereux de faire comme une variable statique dans un fichier source dépend de la variable statique autre dans un autre fichier cpp. Consultez d'initialisation statique fiasco pour plus d'informations.

Si vous modifiez l'initialisation de cMyConstDouble2 à ce ici:

const double cMyConstDouble2 = 2.5*3.14;

Ensuite, votre programme doit se comporter correctement. La raison est que les variables

  • ont le même type POD
  • sont initialisés avec des expressions constantes (1)

sont initialisées au moment de l'initialisation statique. Ces initialisations comprennent

  • zéro initialisation de tous objets ayant une durée de stockage statique
  • initialisations de PODs initialisées avec des expressions constantes

vos variables présentées, seulement cMyConstDouble satisfait les deux conditions d'être complètement initialisé au moment de l'initialisation statique. Cependant, cMyConstDouble2 n'a pas, depuis sa initialiseur ne satisfait pas aux exigences d'une expression constante. Il comprend notamment, une variable qui ne dispose pas de type intégral (ici, il est de type à virgule flottante). Cependant, virgule flottante littéraux sont autorisés dans les expressions arithmétiques constantes. Voilà pourquoi 2.5*3.14 est une expression constante arithmétique. Et c'est pourquoi changer le initialiseur à qui nécessitera d'être initialisé statiquement.


Qu'est-ce qui va se passer avec cMyConstDouble2 si vous restez avec l'expression non-constante? La réponse est, vous ne savez pas. La norme permet cette variable à statiquement initialisé, mais ne nécessite pas de le faire. Dans votre cas, il a été initialisé dynamiquement - donc sa juste valeur après le temps d'initialisation statique était encore nul. Pour avoir une idée de la façon dont compliqué qui est, voici un exemple:

inline double fd() { return 1.0; }
extern double d1;
double d2 = d1; // unspecified:
                // may be statically initialized to 0.0 or
                // dynamically initialized to 1.0
double d1 = fd(); // may be initialized statically to 1.0

Si l'initialisation dynamique ne change pas une autre variable de stockage statique (satisfait dans votre code) et lorsque l'initialisation statique produirait la même valeur que serait produite par l'initialisation dynamique lorsque tous les objets non qui doit être initialisé statiquement serait initialisé dynamiquement (également satisfaite dans votre code) - la variable est autorisée à initialiser statiquement. Ces deux conditions sont également satisfaites dans le code ci-dessus pour les deux variables d2 et d1:

Analyse des d2

  • = d1 ne change pas toute autre variable de stockage statique
  • Lorsque sont initialisés à la fois d2 et d1 dynamiquement, d2 serait alors initialisées à 0.0, car d2 est défini avant d1 et l'initialisation dynamique de d2 saisirait la valeur de d1 comme de l'état juste après l'initialisation statique (où seul zéro initialisation de d1 a eu lieu).

Analyse des d1

  • = fd() ne change pas toute autre variable de stockage statique
  • Lorsque sont initialisés à la fois d2 et d1 dynamiquement, puis = fd() REINITIALISERA d1 à 1.0.

Ainsi, le compilateur peut initialiser d1 statiquement à 1.0, parce que les deux conditions pour l'initialisation-option-statique sont remplies.

  • Si, car il saisira la valeur de d1 comme il était le compilateur décide d'initialiser dynamiquement d2 et d2, puis 0.0 seront réinitialisés à d1 juste après l'initialisation de zéro.

  • Cependant , si le compilateur décide d'initialiser d1 statiquement et d2 dynamiquement, puis d2 sera initialisé à 1.0 , depuis l'initialisation dynamique de d2 va saisir la valeur pleinement initialisées de d1 comme il était juste après initializatio statiquen.

Je ne suis pas sûr de ce que la valeur de d2 est quand d1 et d2 est initialisés statiquement, cependant. Autrement dit, si d2 est censé saisir le 0.0 ou 1.0, car il n'y a pas d'ordre défini pour l'initialisation statique.


(1) Les expressions constantes comprennent aussi des expressions arithmétiques constantes (non seulement des expressions constantes intégrales), en considérant l'ordre d'initialisation d'objets avec une durée de stockage statique.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top