1

Here it is states that

C++ guarantees that variables in a compilation unit (.cpp file) are initialized in order of declaration

Is this the same for C?

Can you quote the relevant standard passages for both C and C++?

Community
  • 1
  • 1
kuga
  • 1,483
  • 1
  • 17
  • 38
  • How could you *possibly* tell in which order the objects are initialized? – EOF Sep 27 '16 at 08:17
  • We haven't established that the C++ quote is correct. Please quote the actual standard. – 2501 Sep 27 '16 at 08:19
  • I am looking for the actual standard. I could not find this! – kuga Sep 27 '16 at 08:21
  • 2
    How is that possible? There are `auto`, there are `static`, then there are local scope.......they will be treated differently...or am I missing something? – Sourav Ghosh Sep 27 '16 at 08:21
  • 1
    @kuga Then the question should perhaps be where does the C++ standard say, and does C say the same? – 2501 Sep 27 '16 at 08:23
  • I only know this behaviour for members and base classes **http://cpp14.centaur.ath.cx/class.base.init.html** – Trevir Sep 27 '16 at 08:24
  • 1
    Section 3.6.2 is probably relevant ([this version](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf) of standard). – Matt Sep 27 '16 at 08:27
  • I don't know about standards, but in real life, C programs compile to sections, one of which is the initialized data section. It is loaded/paged in from disk already initialized. There is no order, everything is already initialized before the first instruction of the program executes. There is no such thing as a constructor in C. There is no order to "run" nonexistent constructors. – doug65536 Sep 27 '16 at 08:47
  • There is no way to write a valid C program that would see the difference. It's not up to the C standard to define wether there's sound or not when a tree that falls in a forest and no one is around to hear it. – Art Sep 27 '16 at 08:51
  • It's moot because the order of initialization doesn't matter in C – M.M Sep 27 '16 at 09:29
  • @SouravGhosh: Local scope is either static or automatic. AFAK C++ has another for temporary objects. But yes, the statement does not make much sense. – too honest for this site Sep 27 '16 at 10:04

3 Answers3

7

Let's start with C. Asking this for C is like asking: If a tree falls in a forest and no one is around to hear it, does it make a sound? It doesn't matter because there is no way to write a valid C program that can tell the difference. This means that it would be pointless for the standard to define this. All we need to know is that by the time any code runs variables with static storage duration have been initialized. The C11 standard draft spells it out in section 5.1.2:

All objects with static storage duration shall be initialized (set to their initial values) before program startup. The manner and timing of such initialization are otherwise unspecified.

In C++ on the other hand, things aren't that easy. It is possible to observe the order of initialization during dynamic initialization. In the standard draft we find section 3.6.2. It quickly gets complicated. It defines the order as: first we do static initialization (this is equivalent to the only thing C can do) and after that dynamic initialization is done. So far so good. We get to this part:

Variables with ordered initialization defined within a single translation unit shall be initialized in the order of their definitions in the translation unit.

and everything is still ok in the world. But then things quickly fall apart:

An implementation is permitted to perform the initialization of a non-local variable with static storage duration as a static initialization even if such initialization is not required to be done statically

This sentence moves us from a predictable world to "it's complicated". The code example in that section of the standard explains this perfectly:

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

In short, in C it doesn't matter, in C++ if you write code that depends on this you'll quite likely to run into trouble when you change compilers.

So your quote is doubly incorrect. Not only isn't initialization done in order of declaration (it's static first, then dynamic), it's also quite fuzzy what is actually static and what is dynamic.

Art
  • 19,807
  • 1
  • 34
  • 60
2

In C++ the order of initialisation has to be defined, since there may be constructors which are called in the initialisation of a variable. Thus C++ defines in which order this code is executed. In plain C there are no constructors. There is no way to tell in which order the variables are initialised, as long as each variable gets initialised before any code that can access the variable is executed.

  • OP is asking for standard quotes. – 2501 Sep 27 '16 at 08:33
  • 1
    @2501 If it doesn't make one iota of difference in which order (global) variables are initialised, the C standard isn't going to bother spelling out any particular order. I strongly suspect there's not going to be anything to quote. –  Sep 27 '16 at 08:35
  • @hvd Explaining that the passages are missing, is a valid answer. This is obvious as questions aren't always true. – 2501 Sep 27 '16 at 08:36
  • @hvd That is not true, kuga did edit that in, I only clarified the wording. Documentation for C and C++ are in fact their standards. It's right here in the edit history if you take a look: https://stackoverflow.com/posts/39719557/revisions You will see my edit does not change the meaning and improves the question. – 2501 Sep 27 '16 at 08:38
  • Please dont argue about that. @hvd Thanks for pointing out, that C standard might not spell it out. – kuga Sep 27 '16 at 08:42
  • Yeah, the arguing here is pointless and not going to lead to anything productive. I'll clean up my earlier comments. –  Sep 27 '16 at 08:44
  • 1
    C++ allows executable code in initializers, that's the main reason (not constructors per se) – M.M Sep 27 '16 at 09:45
0

The C standard (C11) 6.7.6 says

A full declarator is a declarator that is not part of another declarator. The end of a full declarator is a sequence point.

Meaning that at the end of each declaration, the initialization must be done and all sub-expressions must have been evaluated for side effects.

When the actual code is executed isn't specified. Meaning it could be done long before the line where the initialization takes place, but not after that line.

Variables with static storage duration is a special case, since they are guaranteed to be initialized before program startup. Their order of execution wouldn't matter in C, since they can't depend on each other (must be initialized to constant expressions).

In C++, class objects with static storage duration are initialized in an unspecified order and therefore they shouldn't be written so that they rely on each other to be initialized in a certain order.

Also please note 6.7.9/23:

The evaluations of the initialization list expressions are indeterminately sequenced with respect to one another and thus the order in which any side effects occur is unspecified.

Meaning that we can't know the order in which all initializers part of the same declaration are executed.

I believe C and C++ are identical in all of the above, though C++ will also execute constructors as part of the initialization.

Lundin
  • 195,001
  • 40
  • 254
  • 396