3

In the following program, I thought that extern int i; will change the following i to refer to the i defined outside main:

#include <stdio.h>

extern int i=1; // warning: 'i' initialized and declared 'extern'

int main()
{
    int i=2;
    printf("%d\n", i);
    extern int i; // error: extern declaration of 'i' follows declaration with no linkage
    printf("%d\n", i);
    return 0;
}

What is the reason of the "error: extern declaration of 'i' follows declaration with no linkage", where "declaration with no linkage" refers to int i=2;?

After I remove int i=2 in main,

  • the error is gone,
  • the warning "warning: 'i' initialized and declared 'extern'" on extern int i=1; also disappear . Why is that?

Thank you for explanations!

dbush
  • 205,898
  • 23
  • 218
  • 273
  • 2
    error at `extern int i;` : Duplicate identifiers in the same scope. Try `{ extern int i; printf("%d\n", i); }` – BLUEPIXY Aug 16 '17 at 23:28
  • replace extern int i=1; with int i=1; – Ihdina Aug 16 '17 at 23:34
  • You already have a local variable `i` in the `main()`; you can't get at the global one. Local variables hide the global ones. This is not C++ where you have the scope resolution operator to help. And it's bad practice to shadow global variables (GCC will warn if you specify `-Wshadow`). And it's worse practice to want to access both in a single function. – Jonathan Leffler Aug 16 '17 at 23:38
  • @JonathanLeffler Nice to know it is bad practice. My example is more for studying scope and linkage purpose. –  Aug 17 '17 at 00:08

3 Answers3

4
#include <stdio.h>

int i=1;  // external variable

int main()
{
    int i=2;            // local variable
    printf("%d\n", i);  // print local variable i==2

    {
        extern int i;       // point to external variable
        printf("%d\n", i);  // print external variable i==1
    }

    return 0;
}
Ihdina
  • 950
  • 6
  • 21
1

Once you define a variable named i inside your main function, the i at file scope is masked and cannot be accessed (unless you have its address).

When you later add the declaration extern int i, this conflicts with the local variable named i at the same scope since locals can't have external linkage. It does not give you access to the global i.

When you remove the local i, the extern int i declaration matches up with the definition at file scope, so there is no error. As for the warning on extern int i=1;, that did not go away for me on gcc 4.1.2, so that depends on the compiler.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • 1
    Re “locals can't have external linkage”: Linkage is a property of identifiers, and identifiers in block scope certainly can have external linkage. The reason `int i=2; extern int i;` has a conflict is C 2018 (and 2011 and earlier) 6.7 3 gives the constraint that, if an identifier has no linkage (which the `i` in `int i-2;` satisfies), there shall be no more than one declaration of it in the same scope and namespace, with certain exceptions for typedef names and tags. – Eric Postpischil Feb 09 '21 at 22:12
0

Question: What is the reason of the "error: extern declaration of 'i' follows declaration with no linkage", where "declaration with no linkage" refers to int i=2;?
Answer: We do not need to use the extern keyword here on line 3 when it is a single file in a program and there is no other file in the same program or other location on the same file where the variable int i has its definition. There are two main reasons we can use extern keyword in C:
1. When we want to declare a variable explicitly/globally but without its definition.
2. To make the variable globally visible from any other file in a multi-file program or other location of the same file (see Ihdina's exmaple for this scenario).
Compiling your code on my system I get the following error,
error: extern declaration of 'i' follows non-extern declaration . which totally makes sense that the compiler detects the extern on line 9 as a duplicate declaration of the same variable int i on line 7.

Question: After I remove int i=2 in main, the error is gone, the warning "warning: 'i' initialized and declared 'extern'" on extern int i=1; also disappear . Why is that?
Answer: After removing the int i=2; the error was gone on my system but still I have the following warning message:
warning: 'extern' variable has an initializer [-Wextern-initializer] Basically my system (Apple LLVM version 8.1.0 (clang-802.0.42)) does not like the explicit initialization with extern keyword. So, you should modify your code as per Ihdina's answer which compiles without error.

rIz
  • 1
  • 2