Linking various constants / static variables

I have a few questions about communication from the following variables. On examples 7.1.1 / 7 from C ++ 03 and experimenting with compilers (Comeau, Clang and GCC), I came to the following types of links:

  • First static , then extern

     static int a; // (a) extern int a; // (b) valid, 'a' still internal 

    It is clear to me that, in accordance with section 3.5: (a) implies an internal connection. And (b) also implies an internal relationship, because the name "a" is declared static (by (a)).

  • extern first, then static

     extern int b; // (c) static int b; // (d) invalid! 

    First, (c) implies an external connection. But (d) implies an internal relationship, because the name "b" is declared static by (d). This is incorrect in accordance with 7.1.1 / 7, since the implied connection is incompatible.

  • const first, then extern

     const double pi1 = 3.14; // (e) extern const double pi1; // (f) valid and 'pi1' is internal 

    First, (e) implies an internal relationship, since it is a constant and is not declared explicitly extern or previously implied by an external relationship. And (f) should imply external communication and be a mistake, as it explicitly declares the name extern, but compilers keep it internal! Why is that? What is my question.

  • extern first, then const

     extern const double pi2; // (g) const double pi2 = 3.14; // (h) valid and 'pi2' is external 

    Now (g) implies an external connection, because we explicitly declare extern. And (h) also implies an external relationship because (g) is explicitly declared extern.


I experimentally discovered a relationship for 3 and 4 with the following pattern (the second argument is needed for external binding)

 template<typename T, T&> struct ensure { }; ensure<const double, pi1> e1; // failed ensure<const double, pi2> e2; // succeeded 

Summary: The discussion with Charles Bailey turned out to be very fruitful and showed that two interpretations of 3.5/3 possible, where an important marker point reads

A name that has a namespace scope (3.3.5) has an internal relationship if that name

  • An object or reference that is explicitly declared as const, and neither explicitly declared extern, nor previously declared by external relations;

If we look at point (f) , then the two interpretations will come to different conclusions, as shown below

  • The first interpretation notes that pi1 declared const , but also extern declared. Thus, the variable has an external relationship.

  • The second interpretation interprets both occurrences of the “declared” to mean the same declaration. So this means that it is declared const , but not extern const . Note that (e) declared const , not extern const , so we give pi1 internal connection.

Now, which interpretation is correct? I cannot determine from this statement, but the compilers seem to interpret this second way. In particular, if we take the first interpretation, the last cited part 3.5/3 will be redundant, because there would be no valid scenario in which the name would be declared const and previously declared with external communication, but without an explicit extern .

+6
c ++ static extern linkage
source share
3 answers
 const double pi1 = 3.14; // (e) extern const double pi1; // (f) valid and 'pi1' is internal 

My interpretation is as follows. Considering the relationship of a name, we look at previous declarations, as well as one that is interpreted at this stage of the analysis. This is why static int a; extern int a; static int a; extern int a; OK, but extern int b; static int b; extern int b; static int b; not.

When meeting with the first declaration, we note that pi1 explicitly declared const , but none of the declared extern previously declared that it has an external connection. This corresponds to one of the 3.5 / 2 options, so pi1 has an internal binding.

When a second declaration is found, we ask: pi1 name of an object explicitly declared const , but not declared explicitly extern and [... blah ...]. I affirm that this is because it was declared at point (e). Sure, it is not declared this way everywhere, but in the same way a was the name of the declared static object when we looked at the declaration extern int a; , even if it was not declared static everywhere. This, for me, means that the declaration (f) does not imply a different connection from the declaration (e).

+4
source share

I think in # 3 you made a mistake in your analysis. As far as I know, const does not mean anything about communication. I'm not sure how you came to the conclusion that the compiler makes the connection internal. Most compilers will (as an optimization) replace all references to a constant variable with the value that it was initialized, so the character may not appear at all in the code.

And even if you haven’t done this, it’s clear from No. 1 that if something with an internal link is declared with the keyword extern , it remains with the internal link. Therefore, I do not know why you expect errors.

And if const implies internal binding, then # 4 should be a mistake for the same reason as # 2.

0
source share

The presence of both (e) and (f) in the same area of ​​the namespace is simply not valid, in accordance with §7.1.1 / 7 "Links implied by consecutive declarations for this object are agreed."

This rule requires diagnostics.

However, at least Comeau Online does not diagnose the violation.

Cheers and hth.,

EDIT : he, I looked at DR 426 , as mentioned in another answer here, and it seems those who developed the proposed resolution, making it UB instead of being diagnosed, did not know about §7.1.1 / 7. I will not comment on this problem or even raise it in comp.std.C ++, because I found that the standardization work is too political and meaningless (mumbo-jumbo arguments) for me. But in any case, the code is invalid.

0
source share

All Articles