4

Consider this example in [basic.start.static#2], which has a more detail interpretation in cppreference

inline double fd() { return 1.0; }
extern double d1;
double d2 = d1;   // unspecified:
                  // dynamically initialized to 0.0 if d1 is dynamically initialized, or
                  // dynamically initialized to 1.0 if d1 is statically initialized, or
                  // statically initialized to 0.0 (because that would be its value
                  // if both variables were dynamically initialized)
double d1 = fd(); // may be initialized statically or dynamically to 1.0

For the first two remarks about dynamic initialization of d2, there is no doubt here. However, it says the static initialization of d2 is 0.0, I cannot figure out the reason. Since the standard didn't specify the order of the static initialization. In other words, If d1 is used to statically initialize d2, why is the value of d1 at this point definitely zero? The standard only says

If constant initialization is not performed, a variable with static storage duration ([basic.stc.static]) or thread storage duration ([basic.stc.thread]) is zero-initialized ([dcl.init]). Together, zero-initialization and constant initialization are called static initialization; all other initialization is dynamic initialization. All static initialization strongly happens before ([intro.races]) any dynamic initialization.

xmh0511
  • 7,010
  • 1
  • 9
  • 36
  • Note that [this non-normative note](https://eel.is/c++draft/basic.start.static#note-2) has been updated (at some point) to now say "unspecified: either statically initialized to 0.0 or dynamically initialized to 0.0 if d1 is dynamically initialized, or 1.0 otherwise", which make it clearer that the example refers to the state where the static initialization "merely zero-initialized". But these are muddy non-normative waters, as was recently discussed [in this Q&A](https://stackoverflow.com/questions/67991209). – dfrib Aug 10 '21 at 05:38
  • @dfrib Yes, I also suspect that the wording "the static version of the initialization"in the second bullet of [basic.start.static] p3 refers to "zero-initialization" rather than constant initialization. – xmh0511 Aug 10 '21 at 05:42
  • Yes. I'm guessing "static" is used instead of "zero" to emphasize that the case where both variables undergo dynamic initialization _implies_ that there is no constant initialization taking place, meaning static initialization is only zero initialization. – dfrib Aug 10 '21 at 05:46
  • @dfrib If the intent is "zero-initialization", why it does not directly say: *the **zero-initialization** produces the same value in the initialized variable as would be produced by the dynamic initialization if all variables not required to be initialized statically were initialized dynamically.* After all, static initialization version comprises zero-initialization and constant initialization. – xmh0511 Aug 10 '21 at 06:03
  • @dfrib However, even if we rule the second bullet like that. It also has the same problem, if we take the dynamic initialization for `d2` that initialized from `d1` as the static initialization version, what's the value of `d1` at this point? It still depends on the value of `d1`. – xmh0511 Aug 10 '21 at 06:09
  • From the previous discussion around lifetimes on this topic (the Q&A I linked to above) I got the feeling of consensus around this being 1) a corner case in the standard, however still 2) somewhat underspecified. In the lifetimes discussion the question was focused on "could d2 even legally use a partially initialized d1; has the lifetime of d1 started or not d1 is yet to be dynaically initialized?". I think the root confusion is the same, though: underspecification and only a non-normative text (or two) to fall back on. – dfrib Aug 10 '21 at 06:15
  • ... This particular example could probably be made more clear using e.g. "zero-initialization" instead of "static initialization which is implied to be only zero-initialization", but before that it would be good to really sort out the lifetimes issue (linked to Q&A), as the whole example relies on using something (d2 here) to initialize something else (d1 here) possibly before the lifetime of the something (d2) has started, which would imply UB (probably not intended nor implemented as such by implementors). – dfrib Aug 10 '21 at 06:18
  • 1
    @dfrib David, I have issued this [problem](https://github.com/cplusplus/draft/issues/4800). You can freely leave your thoughts there. I think I phrased my thoughts more clearly in there. – xmh0511 Aug 10 '21 at 06:34
  • @dfrib For the lifetime question, My opinion is that zero-initialization **does not** begin the lifetime of the object. Since *The lifetime of an object or reference is a **runtime property** of the object or reference.* zero-initialization, which could be said it is at a compile time. – xmh0511 Aug 10 '21 at 06:38

1 Answers1

0

[basic.start.static]/3:

An implementation is permitted to perform the initialization of a variable with static or thread storage duration as a static initialization even if such initialization is not required to be done statically, provided that

  • the dynamic version of the initialization does not change the value of any other object of static or thread storage duration prior to its initialization, and

  • the static version of the initialization produces the same value in the initialized variable as would be produced by the dynamic initialization if all variables not required to be initialized statically were initialized dynamically.

You know that if d1 and d2 are both initialized dynamically, then d1 is initialized to 0, so if d1 is statically initialized, it should be initialized to 0.

xskxzr
  • 12,442
  • 12
  • 37
  • 77
  • Isn't that what I'm exactly saying? The remark says `d2` is statically initialized by `d1`, however, at this point why is the value of `d1` definitely zero? In other words, the order of the static initialization of these two variables are not specified by the standard. – xmh0511 Aug 10 '21 at 05:23
  • @xmh0511 It does not matter what the value of `d1` is. The rule I quoted describe the *result* of the initialization, not the *process* of the initialization. – xskxzr Aug 10 '21 at 05:27
  • I agree on the value would be 0 if d1 and d2 are both initialized dynamically since their zero-initialization is occurred prior to their dynamic initialization. However, the emphasized rule requires the static initialization of `d2` should be 0 then it can be statically initialized. I'm asking why is the value of `d1` the declaration of `d2` zero? – xmh0511 Aug 10 '21 at 05:27
  • "It does not matter what the value of d1 is" Why? **the static version of the initialization produces the same value in the initialized variable as...**, In other words, the static version of `d2` initialized from `d1` should be zero. It didn't say *the **zero-initialization** produces the same value in the initialized variable as...* – xmh0511 Aug 10 '21 at 05:31
  • @xmh0511 The rule describes the result of the initialization (what final value `d2` should be), so why does the process (what the value of `d1` is) matter? – xskxzr Aug 10 '21 at 05:48
  • I see the difference in understanding between you and me. You construe "provide that" as a "declarative sentence". Instead, I construe "provide that" as "if". Consider the first bullet, it seems it is "if". Only these conditions are satisfied will the dynamic initialization is processed to static initialization. – xmh0511 Aug 10 '21 at 05:54
  • @xmh0511 I don't see any difference. If an implementation does not statically initialize `d2` with 0, it violates this rule. So, as a result, a confirming implementation must initialize `d2` with 0 if it wants to initialize it statically. – xskxzr Aug 10 '21 at 07:06
  • The "conditions" are certainly different from what we say they should be. The dynamic initialization of `d2` is zero, if the bullets after "provide that" are conditions, that means only if the static version of initialization of `d2` should be zero, then the condition is true. see https://en.cppreference.com/w/cpp/language/initialization, it says *if the following conditions are both true*. Do you think "the result is true" is equivalent to "if the result is true"? – xmh0511 Aug 10 '21 at 07:20
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/235813/discussion-between-xskxzr-and-xmh0511). – xskxzr Aug 10 '21 at 07:25
  • Given this example `double d1 = fd(); double d2 = d1;`. Do you think `d2` can be statically intialized to `1.0`? – xmh0511 Aug 11 '21 at 10:18