-2

I reckon this has been probably answered before. Please mark as a duplicate if it has!

I'm having trouble understanding what extern means for local variables (or local functions!). I can't seem to see how it is functionally different from a static local variable... For instance:

int foo(void) {
   extern int i;
   return i++;
}

int bar(void) {
   static int i;
   return i++;
}

AFAICT, foo and bar are the same. The difference according to the C99 spec is that i in foo should have external linkage compared to the i in bar. That said, I can't think of any way to exploit that external linkage - since it is a local variable, it isn't accessible outside of foo, let alone outside of the file.

I'm sure I'm missing something here - what is it?

EDIT

Thank you to everyone who pointed out that I'm missing a type on extern and static. You are quite correct. As a frequent answerer on SO, I now understand the frustration of the barrage of down votes that follow this sort of oversight.

Alec
  • 31,829
  • 7
  • 67
  • 114
  • `foo` only has the declaration of `i`. So it has to be *defined* somewhere with external linkage. And just like how `foo` accesses `i`, some other function can access `i` too. – P.P Nov 13 '17 at 18:34
  • In this context `extern i;` is only a declaration not a definition. This will not compile. http://rextester.com/AMSELK81614 – Stargateur Nov 13 '17 at 18:34
  • @Stargateur: it would indeed compile, if `i` was declared with a type. It simply will not build a valid program without another translation unit containing a *definition* of `i` with external linkage and same type. – Serge Ballesta Nov 13 '17 at 18:38
  • You specify the c99 tag, yet you use implicit int? – DeiDei Nov 13 '17 at 18:53
  • Both `extern i;` and `static i;` are invalid in modern C language, starting from C99. And you tagged your question [c99]. – AnT stands with Russia Nov 13 '17 at 19:14

3 Answers3

1
int foo() {
   extern i;
   return i++;
}

Here you instrument the interpreter to see that i is declared somewhere in some outside block, and to connect this object with an object i declared somewhere before -- in your case, in file scope.

In the second case you tell the interpreter to store the variable i in some permanent storage that is available all long the execution and it is local to the function.

The algorithm of linkage is defined in ISO 9899 in paragraph 6.2.2--Linkage of identifiers. -- part of it:

For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible,23) if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the linkage specified at the prior declaration

See also here

External linkage: An identifier with external linkage represents the same object or function throughout the entire program, that is, in all compilation units and libraries belonging to the program. The identifier is available to the linker. When a second declaration of the same identifier with external linkage occurs, the linker associates the identifier with the same object or function.

alinsoar
  • 15,386
  • 4
  • 57
  • 74
  • OK, so is there any difference between `extern i;` inside `foo` and outside of foo? – Alec Nov 13 '17 at 18:39
  • Oh never mind. Of course there is. `i` may be defined in something being linked against. `extern i;` inside `foo` means `i` is accessible only inside `foo`. – Alec Nov 13 '17 at 18:39
  • So there is no way to connect `i` in `foo` with `i` from `bar`, but if you use `extern i` in other function `xxx`, without previous declaration in some block, the `i` from `foo` will be the same object with `i` from `xxx`. The definition in this case must be somewhere in the file scope. – alinsoar Nov 13 '17 at 18:41
  • Agreed for the first part of that comment. However, surely the definition of `extern i` in some block scope can come from outside the file scope? I mean, it could be coming from some library you are linking against right? – Alec Nov 13 '17 at 18:43
  • @Alec The only difference is that every other function that wants to use `i` needs to duplicate the declaration. Which is why you never see an `extern` declaration in function scope. And, in fact, the `extern` declaration should be in a header file so the compiler can check the ***declaration*** against the ***definition***. – user3386109 Nov 13 '17 at 18:44
  • @Alec Yes, the definition can be also in library, which can be seen as another static object file `.o` passed to the linker. – alinsoar Nov 13 '17 at 18:44
  • `extern i` practically means `search for the object i in some upper block and connect the current object `i` with the same object found in some upper level`. So both `i's` will have the same address in memory, they denote the same object, the same storage location. – alinsoar Nov 13 '17 at 18:46
1

For starters this function definition and the variable declaration

int foo() {
       ^^^
   extern i;
   ^^^^^^^^^
   return i++;
}

are invalid because there is absent a parameter list and a type specifier for the variable i.

It should be written like

int foo( void ) {
         ^^^^
   extern int i;
   ^^^^^^^^^
   return i++;
}

According to the C Standard (6.2.2 Linkages of identifiers)

4 For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible,31) if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the linkage specified at the prior declaration. If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage.

So it is not necessary that the variable i declared in the function has external linkage. For example in this demonstrative program the variable i declared within the function has internal linkage.

#include <stdio.h>

static int i;

int foo( void ) 
{
    extern int i;
    return i++;
}

int main(void) 
{
    printf( "f() = %d\n", foo() );
    printf( "i = %d\n", i );

    return 0;
}

In the function bar that should be defined like

int bar( void ) {
   static int i;
   return i++;
}

the variable i does not have a linkage but it has the static storage duration.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

Extern : extern variable are having external linkage ,main usage of extern varaible to link variable in other file so you are saying "since it is a local variable, it isn't accessible outside of foo" which is wrong, check the below code.

    xyz@xyz-PC:~/s_flow/alec$ vi one.c
    #include<stdio.h>
    int foo() {
            extern i;//this is just declaration, not definition
            return i++;
    }
    main()
    {
            int ret = foo();
            printf("ret = %d \n",ret);
    }

Now linker will try to find definition of "i" in other file or below functions , if not found linker will throw error. when you compile above code you will get linker error. So provide the definition in other file as

xyz@xyz-PC:~/s_flow/alec$ vi two.c
i=100;//this is definition of i

Now compile like gcc one.c two.c & check

static : static storage class having internal linkage it means you can't use static variable outside that file(in which it is declared).

     xyz@xyz-PC:~/s_flow/alec$ vi one.c
     main()
     {
          printf("i = %d \n",i);
     }

Now if I am trying to access static variable which is defined in two.c to one.c , it will throw error.

xyz@xyz-PC:~/s_flow/alec$ vi two.c
void bar() {
   static i = 10;
}
Achal
  • 11,821
  • 2
  • 15
  • 37