Thread: C standard extern with no linkage

  1. #1
    Registered User
    Join Date
    Mar 2009
    Posts
    48

    C standard extern with no linkage

    Hi,

    In C99 draft
    Code:
    For an identifier declared with the storage-class specifier extern in a scope in which a
    prior declaration of that identifier is visible, 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.
    Here is code
    Code:
    #include <stdio.h>
    
    int i = 62; /* external linkage */
    
    int
    main(void)
    {
    	int i = 26;  /* no linkage */
    	extern int i; /* same as last line? */
    	printf("%d\n", i);
    	return 0;
    }
    This can be compiled successfully and the result is "26". But according to the standard, "extern int i" has external linkage, and printf should print "62" other than "26". What happend here? And my gcc version is 3.4.4 with compilation option -std=c99.

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by password636 View Post
    This can be compiled successfully
    Not with gcc 4.3.2 it can't:

    [root~/C] gcc -std=c99 test.c
    test.c: In function ‘main’:
    test.c:9: error: extern declaration of ‘i’ follows declaration with no linkage
    test.c:8: error: previous definition of ‘i’ was here


    I do not think the purpose of extern is to serve as a scoping tool; it is to include variables from other files.

    test.h
    Code:
    int i = 100;
    test.c
    Code:
    #include <stdio.h>
    #include "test.h"
    
    int
    main(void)
    {
    	extern int i;
    	printf("%d\n", i);
    	return 0;
    }
    Last edited by MK27; 09-24-2009 at 09:52 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Registered User
    Join Date
    Mar 2009
    Posts
    48
    Quote Originally Posted by MK27 View Post
    Not with gcc 4.3.2 it can't:

    [root~/C] gcc -std=c99 test.c
    test.c: In function ‘main’:
    test.c:9: error: extern declaration of ‘i’ follows declaration with no linkage
    test.c:8: error: previous definition of ‘i’ was here
    Then how to understand this:
    Code:
    if the prior declaration specifies no linkage, then the identifier has external linkage.
    According to the draft, this means that "extern int i" in my case should not be an error, and it has external linkage. Then with gcc 4.3.2, it is an error. How to understand the relationship between the draft and gcc implementations?

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    I don't follow MK's example, since line 9, so far as I can tell, is return 0 and doesn't have a declaration of i in it. It also doesn't have a redefinition of i either. So that's just confusing.

    As to your example, as you noted the second int i matches the i on the line above it. Once that block-scope variable with no linkage was declared, any chance of getting to the global i vanished forever, or at least until the block ended. Then your extern variable linked to the previous (as in, only visible) declaration -- that's what external linkage means, really: this variable is the same as some other variable somewhere else.

  5. #5
    Registered User
    Join Date
    Mar 2009
    Posts
    48
    Quote Originally Posted by tabstop View Post
    Then your extern variable linked to the previous (as in, only visible) declaration -- that's what external linkage means, really: this variable is the same as some other variable somewhere else.
    So in my case, "extern int i" linked to the "i" in the above line. Then how to understand "no linkage"? I think that "no linkage" means a unique entity and there should not be any other declaration of the same identifier linked to it. But what you say for my case is "a later declaration with extern specifier, which is external linkge, linked to a prior declaration with no linkage", and the result is this: the two "i" is a same entity but have different linkage here.

  6. #6
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    When they say "every declaration with no linkage denotes a unique entity" they mean more or less what they say: no two declarations with no linkage can be linked. That doesn't mean that a declaration with no linkage cannot be linked to at all. A declaration with external linkage can link to some other declaration, either with external linkage or with no linkage.

    Essentially, in your example, the last declaration is just a declaration. Each of the first two had been both a declaration and a definition of a variable. But the third was just a declaration, there was no creation of a new variable -- it merely connected to the previous declaration.

  7. #7
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by MK27 View Post
    I do not think the purpose of extern is to serve as a scoping tool; it is to include variables from other files.

    test.h
    Code:
    int i = 100;
    test.c
    Code:
    #include <stdio.h>
    #include "test.h"
    
    int
    main(void)
    {
    	extern int i;
    	printf("%d\n", i);
    	return 0;
    }
    No, that's not quite how extern is used. A typical case is:


    test1.c
    Code:
    extern int i = 100; /*here extern is optional*/
    test2.c
    Code:
    #include <stdio.h>
    
    int
    main(void)
    {
    	extern int i; /*This can also be put outside of a function*/
    	printf("%d\n", i);
    	return 0;
    }
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  8. #8
    Registered User
    Join Date
    Mar 2009
    Posts
    48
    Quote Originally Posted by tabstop View Post
    When they say "every declaration with no linkage denotes a unique entity" they mean more or less what they say: no two declarations with no linkage can be linked. That doesn't mean that a declaration with no linkage cannot be linked to at all. A declaration with external linkage can link to some other declaration, either with external linkage or with no linkage.

    Essentially, in your example, the last declaration is just a declaration. Each of the first two had been both a declaration and a definition of a variable. But the third was just a declaration, there was no creation of a new variable -- it merely connected to the previous declaration.
    OK. I just had my case compiled with gcc 4.1.1. And it reports:
    Code:
    test.c: In function 'main':
    test.c:9: error: extern declaration of 'i' follows declaration with no linkage
    test.c:8: error: previous definition of 'i' was here
    So this conforms to the definition of "no linkage", that is, a unique entity and any further declaration of the same identifier in its scope denotes a new entirty. Can I think this as follows:
    1) the storage-class-specifier "extern" should be used as only with a declaration, even sometimes it can be initialized at the same time, but this is not what it intended to be.
    2) What tabstop says is right about gcc older version. According to 1), "extern" declaration without an initializer must linked to entity defined somewhere else. Compiler won't assign a new address to it, instead, it must find a defined same identifier visible at the point. This causes the situation that the implementation doesn't conform to the standard about "no linkage". For example, in my case, compiler "has to" link the "extern int i" to the above "i" with no linkage, even if the above i has no linkage.
    3) with gcc 4.1.1 (a relatively newer version), this conformance problem is resolved by not permitting an extern declaration follows declaration with no linkage. This makes sure a no linkage identifier is a unique entity (not linked to either).
    4) As for the following:
    Code:
    if the prior declaration specifies no linkage, then the identifier has external linkage.
    I think it should have a prerequisite: outside any block
    Last edited by password636; 09-24-2009 at 10:27 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Bug in iterator comparison in C++ standard?
    By steev in forum C++ Programming
    Replies: 14
    Last Post: 07-12-2008, 12:02 AM
  2. need help with extern pointers.
    By broli86 in forum C Programming
    Replies: 17
    Last Post: 04-11-2008, 09:16 AM
  3. Replies: 8
    Last Post: 03-08-2008, 08:50 PM
  4. include question
    By Wanted420 in forum C++ Programming
    Replies: 8
    Last Post: 10-17-2003, 03:49 AM
  5. standard language, standard compiler?
    By doubleanti in forum A Brief History of Cprogramming.com
    Replies: 8
    Last Post: 09-03-2001, 04:21 AM