1

I have two 2 files:

a.c:

#include <stdio.h>

extern int i = 5;

int main(){
    prnt();
}

b.c:

#include <stdio.h>

int i;

void prnt(){
    printf("%d",i);
}

The programs compile when linked together using gcc a.c b.c. The output obtained is 5. Shouldn't the gcc compiler give an error saying multiple definiton of i because in a.c, the variable i is both declared and defined and in b.c, the statement int i; is known to implicitly define the value to 0 with a hidden extern?

Piyush Jain
  • 438
  • 4
  • 11
  • What's the result if you delete `int i;` from `b.c`? Will you get a linker error saying `unresolved symbol` (or something along those lines)? – The Paramagnetic Croissant Sep 08 '15 at 05:57
  • 1
    wasn't there an ' initialized and declared' warning, why was it ignored ? – asio_guy Sep 08 '15 at 06:01
  • That code generates two warnings when I compile it, and the warnings are easy to understand. – user3386109 Sep 08 '15 at 06:09
  • I think your premise is wrong. In a.c, i is not defined. extern says it is defined elsewhere. Adding the "= 5" must just give a value to the i that is "defined elsewhere". – Scooter Sep 08 '15 at 06:10
  • 1
    Hmmm, I see in other answers in similar questions people say that in C++ at least "By adding an initialiser to the declaration, it becomes a definition of the global variable. " – Scooter Sep 08 '15 at 06:25
  • 1
    This is essentially the same as [this question](http://stackoverflow.com/questions/1490693/tentative-definitions-in-c99-and-linking), once you realize that `extern int i = 5;` is the same as `int i = 5;` . – M.M Sep 08 '15 at 07:54
  • There was an 'initialized and declared' warning after compilation. There were no other warnings. If I delete int i; from b.c, I obviously get an error saying i 'undeclared'. Also, even if "=5" meant defining somewhere else, wouldn't there be two definition occurrences. – Piyush Jain Sep 08 '15 at 07:56
  • Yes there are two definition occurrences, that's why the code is wrong. The compiler isn't required to tell you about this mistake. – M.M Sep 08 '15 at 09:22

3 Answers3

5

Firstly, to avoid confusion, extern int i = 5; is exactly the same as int i = 5;. It is a definition because of C11 6.9.2/1:

If the declaration of an identifier for an object has file scope and an initializer, the declaration is an external definition for the identifier.

(Note that "external definition" here means a definition at file scope - not to be confused with "external linkage").

int i; is called a tentative definition ; in this case it behaves the same as int i = 0; (this is defined by 6.9.2/2), confirming that it is a definition. It has external linkage because of 6.2.2/5:

If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external.

So both of those definitions define i with external linkage. Section 6.2.2/2 of the C standard says:

[...] each declaration of a particular identifier with external linkage denotes the same object or function.

So both of these i denote the same object.

From 6.9/5:

If an identifier declared with external linkage is used in an expression (other than as part of the operand of a sizeof or _Alignof operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for the identifier

Since you have provided two definitions for i , your program violates this rule, causing undefined behaviour with no diagnostic required.


The reference for rule violation being undefined behaviour is 4/2:

If a ‘‘shall’’ or ‘‘shall not’’ requirement that appears outside of a constraint or runtime-constraint is violated, the behavior is undefined.

The quoted section from 6.9/5 is a "Semantic:", not a "Constraint:", so it counts as appearing outside of a constraint.

M.M
  • 138,810
  • 21
  • 208
  • 365
-1

The answer for this question is:

  • Declaration can be done any number of times but definition only once.
  • if a variable is only declared and an initializer is also provided with that declaration, then the memory for that variable will be allocated i.e. that variable will be considered as defined. so extern int i = 5; it declare as well as allocate the memory for variable now we can declare the i variable n number of times.
suren
  • 455
  • 3
  • 14
-2

The answer is "declaration can be done any number of times whereas definition can be done only one time"

To make it clear, whenenever an "extern" keyword is used before a variable, it means that the variable is just declared.

extern int i = 5; -> This just declares a variable

int i; ---> Defined and declared

hazzelnuttie
  • 1,403
  • 1
  • 12
  • 22
  • 1
    then how about this : http://ideone.com/QmyChK here variable is declared `extern` according to you but it is giving **5** as an output. – surajs1n Sep 08 '15 at 06:27
  • @psyco Please note that he has actually compiled files a.c and b.c together – hazzelnuttie Sep 08 '15 at 06:42
  • @psyco Also please note that he has used user defined function "prnt" defined in b.c and not the standard function "printf – hazzelnuttie Sep 08 '15 at 06:48
  • 1
    So what, if you declare as `extern int i = 5` it **doesn't** mean it is just declared, it means it is **declared** and as well as **defined** in `a.c` file itself. There is no role of `b.c` in it. – surajs1n Sep 08 '15 at 06:51
  • @psyco I think a better understanding of definition and declaration would help. "Definition" is a must and it where the memory is allocated for the variable and that is the role of b.c. The variable declaration using "extern" keyword just extends the visibility of the already defined variable in file b.c to a.c – hazzelnuttie Sep 08 '15 at 06:56
  • 1
    `extern int i = 5;` is both declared and defined – M.M Sep 08 '15 at 06:59
  • @M.M thanks for pointing out... it is just declared in the sense no memory is allocated for that variable – hazzelnuttie Sep 08 '15 at 07:00
  • 1
    Memory is allocated for it and `5` is stored in that location – M.M Sep 08 '15 at 07:24
  • @M.M memory is allocated in b.c and 5 is assigned in a.c – hazzelnuttie Sep 08 '15 at 07:46
  • 2
    @hazzelnuttie memory isn't allocated in either file specifically. This program causes undefined behaviour because both `int i = 5;` and `int i;` attempt to allocate memory for `i` . (see my answer for explanation using technical terms). – M.M Sep 08 '15 at 07:56
  • 1
    The 5th example on this site (says that extern int a = is actually both declaration and definition, is it true?): http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/ – Piyush Jain Sep 08 '15 at 08:04
  • @PiyushJain Yes that is true – M.M Sep 08 '15 at 08:08