1

If there is multiple declarations possible and only one definition is allowed (ref), then why does the code below give me an error as multiple declaration for i in Turbo C++ compiler?

int main()
{
    extern int i;
    int i;
    printf("The value of i is %d",i);
    return 0;
}
Community
  • 1
  • 1
Rohit Saluja
  • 1,507
  • 1
  • 14
  • 25
  • @al-Acme I understood the difference between both but dont know why this code is giving me the error. – Rohit Saluja Dec 18 '14 at 07:19
  • Declare `extern int i` in global scope. – cpx Dec 18 '14 at 07:20
  • 1
    Note that the `extern int i;` says "there is a variable `i` declared somewhere else", and the `int i;` says "here is a variable `i`", which means there are two different declarations for `i` here, hence the redeclaration error. If the `extern` and `int` lines were at file scope, then the first would say "there is a global variable `i` somewhere" and the second would say "here is a (tentative) definition of a global variable `i`" and the two are not conflicting. The definition is tentative because it is not initialized; that gets into some tricky areas in C. – Jonathan Leffler Dec 18 '14 at 07:25
  • @Jonathan Leffler but is'nt it true that we can declare a variable multiple times than why the multiple declaration error? and also as extern int i will tell compuiler that somewhere there is some variable i and in the very next line the memory is given to that variable than what is the problem with the code ..? – Rohit Saluja Dec 18 '14 at 07:29
  • @RohitSaluja: If you write `int i; int i;` inside a function, you will get an error. You could write: `{ int i; { int i; … } … }` and then there are two scopes, and the inner `i` hides the outer. In the 'inside a function, writing `extern int i; int i;` is approximately equivalent to the `int i; int i;` case except that the first declaration says "`i` is declared somewhere outside this function" too. Note that `extern int i; extern int i;` would be OK. (And both GCC and G++ give an error on the code in the question; it is not that Turbo C++ is ancient and no longer correct.) – Jonathan Leffler Dec 18 '14 at 07:34
  • why `extern int i; extern int i;` would be ok? – justmscs Dec 18 '14 at 07:36
  • Note that `i` has no linkage in local scope so you cannot write `extern i` to say that there's a variable defined somewhere that has an external linkage so they don't match. – cpx Dec 18 '14 at 07:38
  • @Jonathan Leffler as you mentioned that writing **extern int i** and **int i** inside the function is similar as writing **int i** and **int i**. Then does it implies that writimng **extern int i** at a block scope also defines i ? and also just to bring to the attention in the very first comment you said that writing ** If the extern and int lines were at file scope, then the first would say "there is a global variable i somewhere"** but isnt the scope of the variable is determined where it is defined ? as **extern int i** at file scope will only declare it. Am i correct ? – Rohit Saluja Dec 18 '14 at 08:52
  • @RohitSaluja: No; one of the dissimilarities is that the `extern` declaration does not define any storage space; it simply says that a definition somewhere else defines the storage. – Jonathan Leffler Dec 18 '14 at 08:54
  • Please clarify whether you are compiling as C or C++ – M.M Dec 19 '14 at 01:21
  • Well if I compile the code as C then it gives me some error stating declaration of i with no linkage, and when I compile it in C++ it says redclaration of **i** – Rohit Saluja Dec 19 '14 at 04:34

2 Answers2

5

Names either have linkage or they do not. Names with linkage can have either external or internal linkage.

"Linkage" is how the standard refers to the visibility of a name within a translation unit (a "translation unit" is simply the contents of a source file after preprocessing):

[basic.link]

(2.1) — When a name has external linkage , the entity it denotes can be referred to by names from scopes of other translation units or from other scopes of the same translation unit.

(2.2) — When a name has internal linkage , the entity it denotes can be referred to by names from other scopes in the same translation unit.

(2.3) — When a name has no linkage , the entity it denotes cannot be referred to by names from other scopes

The linkage of declarations has to match, you are trying to redeclare (and define) a variable previously declared with external linkage as a variable with no linkage.

[dcl.stc]

7 The linkages implied by successive declarations for a given entity shall agree. That is, within a given scope, each declaration declaring the same variable name or the same overloading of a function name shall imply the same linkage. [...]

int main()
{
  extern int i; // declare i with external linkage
  int i;        // define  i with no linkage **ERROR**
}

As the standard implies, if the declarations are in different scopes this isn't an issue as they refer to different names:

int main()
{
  extern int i; // declare i with external linkage
  {
    int i;      // define i with no linkage (shadows the previous declaration)
  }
}

This also works fine at global scope because variables and functions at (non-anonymous) namespace scope without an explicit static declaration have external linkage:

extern int i; // declare i with external linkage
int i;        // define  i with external linkage

extern int j; // declare j with external linkage
static int j; // define  j with internal linkage **ERROR**

static int k; // define  k with internal linkage
extern int k; // declare k with internal linkage (!!)

int main()
{
}

The example with k is a little counterintuitive: a name declared with extern will only have external linkage if no previous declarations of the same name exist in the same scope, otherwise the linkage will be unchanged. This isn't an error, unless the name was previously declared with no linkage, which is why you cannot redeclare local variables for instance.


You can find a quick summary of the linkage rules on cppreference.

Community
  • 1
  • 1
user657267
  • 19,343
  • 5
  • 50
  • 73
0

@user657267 has given a good answer, however, as your comment to his/her answer suggests, you are even more confused and you want a less technical answer. I will give it a try...

extern int i; says i is a 'global' variable defined somewhere else.
int i; says i is a 'local' variable defined in side the function.

The first statement is a declaration and the second is a declaration as well as a definition. The former statement says that i lives in the world named global and the other says that the i lives in the world named local. Even though they are from different worlds and thus different entities, inside function main() i.e. in side the local world their same names create confusion and thus the compiler complains about multiple declaration.

Imagine your school having two students with the same full name! One is from a different state/country. Wouldn't the principal complain about duplicate entries for the same person?

RcnRcf
  • 346
  • 1
  • 8
  • Why would the principal complain? It does happen that you get people with the same name, you can't turn students away for that – M.M Dec 19 '14 at 02:33
  • @RD445 the statement **extern int i** doesnt always implies that i is a global variable or does it ? Go to this Link http://ideone.com/eXfduL Isnt it the definition pasrt which determines the Scope of the variables? – Rohit Saluja Dec 19 '14 at 04:49
  • @RohitSaluja That link also shows that an undefined reference error is produced by the compiler. You probably missed that point. extern is sensible only if the identifier it is declaring is defined as a global somewhere in the program. – RcnRcf Dec 19 '14 at 14:22