-1

What does this statement extern int x=4; mean in C? Is it similar to int x=4;?

when i am compiling the code extern int x=4; outside a block(function) ,the compiler raises a warning, not error.

Warning:-

warning: 'x' initialized and declared 'extern' extern int x=3;

Meanwhile when i am compiling the code extern int x=4;inside a block(function), the compiler raises an error .

Error:-

error: 'x' has both 'extern' and initializer extern int x=3;

What's going on , i am not getting.What does the statement extern int x=4; mean actually? Please clear the concept.

Thanks in Advance...

Abhishek Jaiswal
  • 288
  • 2
  • 14
  • 3
    Maybe post the warning and error you are getting? Have you looked up documentation on the extern keyword or seen this post: https://stackoverflow.com/questions/496448/how-to-correctly-use-the-extern-keyword-in-c ? – Joe Davis Apr 21 '21 at 14:40
  • 1
    extern tells the compiler that the variable is defined somewhere else and will be found at link time. Since it isn't your variable, initializing it is a mistake. – stark Apr 21 '21 at 14:50
  • 1
    `extern int x;` will instruct the linker to know that someone else is responsible for declaring *and* initializing `x`, not you. So you can not initialize it. – arfneto Apr 21 '21 at 14:53
  • @arfneto i am talking about "extern int x=4; " , not just "extern int x;". – Abhishek Jaiswal Apr 21 '21 at 14:55
  • 3
    This is what I am telling you (and others are telling): you are talking about initializing an external `x` variable and it makes no sense. `x` may be external in a dozen modules. But as in `Highlander` *there can be only one* point when `x` can be initialized, And is is the module where it is not `extern` to.... – arfneto Apr 21 '21 at 14:59
  • @arfneto: What rule in the C standard does `extern int x = 4;` violate? – Eric Postpischil Apr 21 '21 at 15:03
  • You can not initialize something you `do not have`. How could the compiler resolve 2,3 or `x` conflicting initializations? `extern` means the actual address is provided further away by the linker. – arfneto Apr 21 '21 at 15:31
  • @arfneto: Re “`extern` means the actual address is provided further away by the linker”: That is not what the C standard says. Per C 2018 6.2.2 4 says it affects the linkage of the identifier, and it does not say you cannot define something declared with `extern`. There is even an example in C 2018 6.9.2 4: `extern int i3 = 3; // definition, external linkage`. So the C standard tells us quite clearly the things you are saying are wrong. – Eric Postpischil Apr 21 '21 at 16:43
  • @arfneto: Re “How could the compiler resolve 2,3 or x conflicting initializations?”: Nobody is suggesting multiple definitions. – Eric Postpischil Apr 21 '21 at 16:44
  • initialization is not definition. Doing as the standard say implies in some cooperation between the modules, something like the underscore in Python: there is no private variable but if you see an `_ ` as the first letter you should cooperate and do not change it. – arfneto Apr 21 '21 at 18:42
  • @arfneto: Any declaration for an identifier for an object with an initializer is a definition. There is no suggestion of either multiple initializations or multiple definitions in this question. As the example in the C standard shows, `extern int i3 = 3;` is a legal definition. Also, please write `@username` when responding to somebody; it is conducive to help readers know to whom you are responding and is courtesy. – Eric Postpischil Apr 21 '21 at 23:01

2 Answers2

4

The meaning of extern is a bit complicated because C was developed over time by different people trying different things, rather than being designed from the start with knowledge of what the end product should be.

The reason extern int x=4; inside a block is an error is it violates this rule in C 2018 6.7.9 5:

If the declaration of an identifier has block scope, and the identifier has external or internal linkage, the declaration shall have no initializer for the identifier.

I am not sure what the exact motivation for that rule is. One motivation might be, “The compiler is busy defining a function here, and defining another thing at the same time is unexpected, awkward, or difficult for the compiler.” I am not sure it would actually be difficult to implement, but maybe it could be a problem for some compilers, especially early compilers way back when.

A reason for the warning is that we usually use extern with declarations to say “We are only declaring this identifier to tell you about an object defined somewhere else.” That is a matter of common practice, not a rule.1 But the initialization says “We are defining an object here.” So that is a contrast, and the compiler warns you about it. However, it is not an actual rule violation, so the compiler does not report it as an error.

Footnote

1 There are rules that fit this practice. At file scope, int x; is a tentative definition, whereas extern int x; is a declaration that is not a definition. So that comports with the practice; extern int x; says we are just declaring x, whereas int x; says we might be defining it. However, int x = 4; and extern int x = 4; are both definitions and do not violate any rule.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
-1

Intuitively, I like to think of extern as "reference a (global) object in another file." You can't define a global object inside a function, so that concept makes no sense.

The initialization of an extern variable is possible, but not recommended. If the instantiation is not initialized, and you're conditionally adding one of a set of files that initializes the variable, and multiple that use it. That's probably a bad idea, but if you're blocking off a special part of memory in the declaration, I could see a use case for it. Another use case is if it COULD be a global variable in another file, but you may or may not be including that file. In the case there is no external declaration, the compiler will allocate memory for you and treat it like a regular global variable.

If you initialize multiple values in multiple files, you'll almost certainly get a linker error.

yhyrcanus
  • 3,743
  • 2
  • 23
  • 28
  • Re “global object”: C does not have any global scope, just file scope and external linkage. It is the identifier that would be global or have file scope and/or external linkage, not the the object. The object is just memory, not the name. – Eric Postpischil Apr 21 '21 at 15:09
  • Re ”that concept makes no sense”: Why? If I had `int get(void) { extern int x = 3; return x; } void set(int value) { extern int x; x = value; }`, what would be nonsensical about that? `x` is declared with external linkage, an object is defined for it, and `x` is declared again with external linkage in another scope, so the external linkage causes them to refer to the same object. I do not see a semantic or implementation barrier to this. It seems to be a choice made by C, not a logical requirement. – Eric Postpischil Apr 21 '21 at 15:15
  • Re “If you assign multiple values in multiple files, you'll almost certainly get a linker error.”: Do you mean “initialize”, not “assign”? There is nothing wrong with assigning values to an external variable in multiple source files. – Eric Postpischil Apr 21 '21 at 15:17
  • @EricPostpischil RE "global": 1000% true. "Globally" scoped as opposed to function scoped or translation unit-scoped (ie declared static). You still need to link out to it, so it's not really "global" but it's as global as it needs to be. – yhyrcanus Apr 21 '21 at 16:12
  • RE extern inside a function logically: It's declaratory concept, so declaring extern inside a function would be declaring a link to this external object, but scoped only to a given function? If it's available in memory, it doesn't make sense to scope inside a function rather than the whole translation unit. Maybe that's just a limitation in my own thinking. – yhyrcanus Apr 21 '21 at 16:24