Proč někteří const proměnné, které se některé vyvážené const proměnné získat hodnotu 0?

hlasů
2

Zvažte následující. Mám dvě vyvážené konstanty takto:

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

a

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

Tyto konstanty jsou nyní odkazoval se na nějaké místo jinde definovat dvě statické (místně viditelných) konstanty:

// 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);

Což dává následující výstup:

cAnotherDouble = 3.454, cAnotherDouble2 = 0

Proč je druhý double 0? Jsem pomocí .NET 2003 C ++ kompilátoru (13.10.3077).

Položena 28/05/2009 v 13:35
zdroj uživatelem
V jiných jazycích...                            


4 odpovědí

hlasů
9

Nebudu se ponořit svůj prst do problematiky zde externí, ale proč si prostě umístit consts v příslušných hlavičkové soubory a zapomenout „exportu“ je pomocí extern? To je, jak se consts měla být použita v C ++, a proč mají vnitřní vazby.

Jinými slovy:

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

a #include tento soubor tam, kde je potřebujete.

Odpovězeno 28/05/2009 v 13:42
zdroj uživatelem

hlasů
8

Vzhledem k tomu, cMyConstDouble je deklarován jako extern, kompilátor není schopna převzít svou hodnotu a negeneruje čas inicializace sestaví za cMyConstDouble2. Vzhledem k tomu, cMyConstDouble2 není kompilaci inicializována, jeho pořadí inicializace vzhledem k cAnotherDouble2 je náhodná (nedefinováno). Viz statické inicializační fiasko pro více informací.

Odpovězeno 28/05/2009 v 13:42
zdroj uživatelem

hlasů
3

To je nebezpečná věc dělat jako jeden statické proměnné v jednom zdrojovém souboru závisí na jiné statické proměnné v jiném souboru cpp. Zkontrolujte, zda statické inicializační fiasko pro více informací.

Odpovězeno 28/05/2009 v 13:44
zdroj uživatelem

hlasů
2

Změníte-li inicializaci cMyConstDouble2to tady:

const double cMyConstDouble2 = 2.5*3.14;

Pak váš program by se měl chovat správně. Důvodem je to, že proměnné, které

  • Mají typ POD
  • Jsou inicializovány s konstantními výrazů (1)

jsou inicializovány při statickém době inicializace. Tyto zahrnují inicializace

  • Nula inicializace všech objektů, které mají statickou trvání skladovací
  • Inicializace lusků inicializovány konstantními výrazů

Z vašich uvedených proměnných, pouze cMyConstDoublesplňuje obě podmínky, že budou plně inicializován při statickém době inicializace. Nicméně, cMyConstDouble2není, protože jeho Inicializátor nesplňuje požadavky na konstantní výraz. Zejména obsahuje proměnnou, která nemá integrální typ (zde, má plovoucí typu bod). Nicméně, s plovoucí desetinnou čárkou literály jsou povoleny v aritmetických konstantních výrazů. To je důvod, proč 2.5*3.14je aritmetický konstantní výraz. A to je důvod, proč měnit inicializátor na které bude vyžadovat, aby se staticky inicializaci.


Co se stane se cMyConstDouble2, když se zůstat s non-neustálé vyjadřování? Odpovědí je, že nevím. Tento standard umožňuje, že proměnná má být staticky inicializaci, ale nevyžaduje, aby tak učinily. Ve vašem případě to bylo dynamicky inicializovat - tedy jeho hodnotu bezprostředně po statické čas inicializace byl stále nula. Chcete-li získat cit pro to, jak složité to znamená, že zde je příklad:

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

V případě, že dynamické inicializace nemění žádný jiný statické skladovací proměnnou (splněn ve vašem kódu), a když by statická inicializace produkovat stejnou hodnotu, jako by byly produkovány dynamickým inicializace, když všechny objekty, které nemusí být staticky inicializaci bude inicializaci dynamicky ( spokojeni ve vašem kódu) - pak je proměnná nemá inicializovat staticky. Tyto dvě podmínky jsou splněny ve výše uvedeném kódu pro obě proměnné d2a d1:

Analýza d2

  • = d1 nemění žádný jiný statické skladovací proměnnou
  • Když oba d2a d1inicializaci dynamicky, pak d2bude inicializována 0.0, neboť d2je definován dříve d1, a dynamické inicializace d2by se chytit hodnotu d1ke stavu bezprostředně po statické inicializaci (kde jen nula inicializace d1konal).

Analýza d1

  • = fd() nemění žádný jiný statické skladovací proměnnou
  • Když oba d2a d1inicializaci dynamicky, pak = fd()bude inicializovat d1na 1.0.

Takže kompilátor může inicializovat d1staticky 1.0, protože jsou-li splněny obě podmínky pro volitelnou-statickou inicializaci.

  • Pokud kompilátor rozhodne inicializovat d1a d2dynamicky, pak d2bude inicializována0.0 , neboť se chytit hodnotu d1, jak to bylo těsně po nula inicializace.

  • Nicméně , pokud překladač rozhodne inicializovat d1staticky a d2dynamicky, pak d2bude inicializována1.0 , neboť dynamické inicializace d2se chytit plně inicializované hodnotu d1, jak to bylo těsně po statické inicializaci.

Nejsem si jistý, co hodnota d2je, když d1 i d2 inicializaci staticky, ačkoli. To znamená, zda d2má chytit 0.0, nebo 1.0, protože není tam žádná objednávka definována pro statické inicializaci.


(1) konstantní výrazy zahrnují aritmetické konstantní výrazy příliš (nejen integrální konstantní výrazy), když s ohledem na inicializační pořadí objektů se statickým dobu skladování.

Odpovězeno 28/05/2009 v 17:00
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more