-4
int x;          // global x, 0 initialized.
extern int y;   // its storage duration, scope and linkage is equivalent to above.
int z = 5;
int main(){ return 0;}

According to https://stackoverflow.com/a/28610934/2402272, the rule says:

The default storage duration, scope and linkage of variables declared outside any block, at the outer most level, have static storage duration, file scope and external linkage.

x cannot be defined in another source file as it is not marked as extern, doing so is undefined behaviour: How do I use extern to share variables between source files?

z also cannot be defined in another source file as we will get multiple definition error at link time.

so neither x nor z can be usefull with external linkage. Why are they extern by default then?

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
Dan
  • 2,694
  • 1
  • 6
  • 19
  • 2
    Make it static if it's not meant to be exported. `extern` doesn't mean to share it externally. It means "it's external, defined somewhere else". Useful for header files. – user2740650 Jul 11 '21 at 17:24
  • 1
    See this for more detail: https://stackoverflow.com/a/1410632/2740650 – user2740650 Jul 11 '21 at 17:25
  • Do you mean to ask why variables declared *at file scope* have external linkage by default? Because having external linkage is necessary for an identifier to be global, as most people mean that term. – John Bollinger Jul 11 '21 at 17:43
  • Also, it would help to clarify what you mean by "neither `x` nor `z` can be usefull with external linkage". I don't see how that follows from your preceding comments, and I'm unsure whether that's because you have a misunderstanding about the language semantics or because what you mean by "be usefull" is not among the possibilities I have considered. – John Bollinger Jul 11 '21 at 17:47
  • @JohnBollinger I thought my question's clear enough, having globals without the `extern` keyword is undefined behaviour and unless (if tried to be used in another source file) why do they need to be visible globally? – Dan Jul 11 '21 at 17:52
  • It's not quite so simple, @user2740650. `extern` *does* mean that the declared identifier has external linkage (which is also the default), and if the variable is declared at file scope with an initializer then that is all it means. – John Bollinger Jul 11 '21 at 17:52
  • @Dan, to most people, "global" means visible and accessible throughout the program. Having external linkage is inherent in that. – John Bollinger Jul 11 '21 at 17:54
  • but it's not, `x` and `z`CANNOT be used globally in multiple files as is. you have to explicitly mark them as `extern`. – Dan Jul 11 '21 at 17:54
  • That is not true, @Dan. They can be used globally as long as all other translation units that want to access them declare them explicitly `extern` (and do not include initializers in those declarations). – John Bollinger Jul 11 '21 at 17:56
  • @JohnBollinger that's what I just said. extern is not used here, and im saying assume it's not used in other source files either. – Dan Jul 11 '21 at 17:58

3 Answers3

1

It is true that x and z cannot be defined in another source file because they are already defined. They can however be declared in another file so that they may be used.

If you had the following in another source file:

extern int x;
extern int z;

Then you would be able to use both x and z in that source file.

Also, if your code was compiled by itself into an executable, the linking stage would fail because y was declared but not defined.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • so `extern int x;` in another file will make `x` equal to 0 in this example right? as globals are 0 initialed by default. – Dan Jul 11 '21 at 18:02
  • 1
    @Dan Since `x` is defined in your original file without an initializer it is implicitly initialized to 0. An `extern` declaration in another file doesn't change that. – dbush Jul 11 '21 at 18:03
  • i know, i was confirming if `x` was defined as `0` in the entire program since it will be 0 initialized in my original file. – Dan Jul 11 '21 at 19:00
  • @Dan, there is only one external `x`. That is the point. Its initial value is determined by its definition, which is part of the reason why there must be only one of those. Its value at any given time is not dependent on the source file from which it is accessed. – John Bollinger Jul 11 '21 at 19:05
  • @JohnBollinger i don't think you're getting it. `extern int x;` is not initialized to anything, even if it's global, it's extern. `int x;` is also not explicitly initialized to anything but since its global, compiler initializes it to 0, therefore `x` will be 0 in the entire program, this is what I was confirming. – Dan Jul 11 '21 at 19:07
  • I agree, Dan, I don't get the source of your confusion. But I understand the language semantics very well indeed. – John Bollinger Jul 11 '21 at 19:08
0

Why do globals have external linkage by default?

“Why” questions can sometimes be answered by reasons of design, historical documents, or other information, but this one is likely largely due to how early C developed over time, so the C standard essentially adopted existing practices.

The rule says:

The default storage duration…

I find no such rule in the C 2018 standard. Cite your source.

x cannot be defined in another source file as it is not marked as extern,…

This is not true, strictly speaking. You can define x in another translation unit. The resulting behavior will not be defined by the C standard. However, it may be defined by the compiler and/or other tools used to build and execute the program. In fact, in GCC versions prior to 10, GCC defined the behavior to treat tentative definitions as common symbols by default.

… so neither x nor z can be usefull with external linkage. Why are they extern by default then?

This conclusion is incorrect. Both the x and z defined with int x; and int z = 5; can be used in other translation units by declaring them there as extern int x; and extern int z.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • here's my source: https://stackoverflow.com/a/28610934 – Dan Jul 11 '21 at 17:59
  • 1
    @Dan: Put information for the question in the question, not in comments. – Eric Postpischil Jul 11 '21 at 18:02
  • I didn't find it necessary. – Dan Jul 11 '21 at 18:58
  • 2
    @Dan: Stack Overflow is supposed to be a repository of questions and answers for future readers, not a personal service to you. Questions should be self-contained with all the information needed to understand them. And the purported “rule” you quoted is not a rule; it is something somebody said, not an authoritative rule from the C standard. So it is not a good basis for supposition about the rules of C. If you will not use Stack Overflow according to the guidelines and edit your questions to make them good quality questions that will serve others in the future, then expect to be voted down. – Eric Postpischil Jul 11 '21 at 19:01
0

Why do globals have external linkage by default?

This is at least in part a result of the historical development of C, as @EricPostpischil already remarked.

From a modern perspective, I might suggest that because relying on external variables and even internal variables is usually poor practice, language design considerations related to those may not have been weighted very heavily. However, projecting that viewpoint onto Dennis Ritchie may be anachronistic.

In fact, I think it more likely that in the day, Ritchie assumed that programmers declaring file-scope variables would usually want them to be accessible throughout the program, not just in the source file where they appear. That is, that they would usually want external linkage. If he did assume that then I think he was right. The same applies to functions, too, where the decision is less controversial, and the result that the rules for the linkage of file-scope variable and function identifiers are consistent is a gratifying outcome.

With respect to the example code:

x cannot be defined in another source file [...]

Agreed, supposing that "cannot" is understood as being qualified by "without producing undefined behavior".

z also cannot be defined in another source file [...]

Agreed, subject to the same caveat as above.

so neither x nor z can be usefull with external linkage.

Not agreed. x and z cannot be defined again elsewhere without producing UB, but they can be declared again, in the same translation unit or others. Where an external declaration of them is in scope, they can be accessed. That an additional keyword must be supplied in declarations in other translation units does not make it useless for x and z to have external linkage by default. Nor is it unreasonable that the programmer is obligated to pay attention to ensuring that there is only one external definition of those variables.

Perhaps you are coming to this from the perspective that there is a trap here for the unwary, which there is. But that's an entirely different question from the default choice of linkage.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157