11

When I compile the code below

#include<stdio.h>

int main()
{
  int a;
  int a = 10;
  printf("a is %d \n",a);
  return 0;
}

I get an error:

test3.c: In function ‘main’:
test3.c:6:5: error: redeclaration of ‘a’ with no linkage
test3.c:5:5: note: previous declaration of ‘a’ was here

But if I make the variable global then it works fine.

#include<stdio.h>

int a;
int a = 10;
int main()
{
  printf("a is %d \n",a);
  return 0;
}

Why is declaring the same global variable twice not an error, but doing that for a local variable is an error?

Praetorian
  • 100,267
  • 15
  • 224
  • 307
Jeegar Patel
  • 23,639
  • 42
  • 138
  • 202

3 Answers3

18

In C, the statement int a; when made at file scope, is a declaration and a tentative definition. You can have as many tentative definitions as you want, as long as they all match each other.

If a definition (with an initializer) appears before the end of the translation unit, the variable will be initialized to that value. Having multiple initialization values is a compiler error.

If the end of the translation unit is reached, and no non-tentative definition was found, the variable will be zero initialized.

The above does not apply for local variables. Here a declaration also serves as a definition, and having more than one leads to an error.

Praetorian
  • 100,267
  • 15
  • 224
  • 307
  • In case of local variable, since declaration and definition is same, why we get re-declaration error and why not re-definition error? In case local variable, we are actually definining and hence the error should have been re-definition right? – Rajesh Jun 15 '17 at 06:06
  • See C11, [6.9.2 External object definitions](http://port70.net/~nsz/c/c11/n1570.html#6.9.2) – Paul Ogilvie Dec 24 '17 at 16:01
  • While correct, doesn't really answer the question. The real reason is that you're only allowed to have one declaration of a name in *most* scopes. The exeception is file scope -- you can have any number of declarations for a name at file scope as long as they are compatible. This is independent of any definitions. – Chris Dodd Dec 26 '17 at 02:46
2

The other reason I could think of is that un-initialized global variables are stored in the BSS (Block Structured Segment) where are the global variables that are initialized are stored in Data Segment.

I am guessing that there is some kind of a name space resolution and when there is a conflict the variable in the Data segment overrides the one in the Block Structured Segment.

if you were to declare

int a =5 int a = 10

in the global scope (both in the data segment) there would be conflict as expected.

liv2hak
  • 12,597
  • 41
  • 127
  • 231
  • 2
    According to your explanation, there should be two copies of `a`, one each in the bss and data segments (which are implementations details anyway, never mentioned in the standard). – Praetorian Jan 22 '14 at 07:32
1

You can't have two global variables with the same name in C program. C might allow multiple definitions in the same file scope through the tentative definition rule, but in any case all definitions will refer to the same variable.

Local Variable

In C, multiple local variables are not "merged" into one.

All the local variables with the same name will be referring to the different int-sized piece of memory.

 #include<stdio.h>

 int main()
 {
  int a;
  int a = 10;
  printf("a is %d \n",a);  
  return 0;
 }

So when assigning the memory to the redeclaration of the same variable it gives an Error.

Global Variable

In C, multiple global variables are "merged" into one. So you have indeed just one global variable, declared multiple times. This goes back to a time when extern wasn't needed (or possibly didn't exist - not quite sure) in C.

In other words, all global variables with the same name will be converted to be one variable - so your

#include<stdio.h>

int a;
int a = 10;
int main()
{
printf("a is %d \n",a);
return 0;
}

will be referring to the same int-sized piece of memory.

alk
  • 66,653
  • 10
  • 83
  • 219
Vaibhav Jain
  • 3,607
  • 3
  • 23
  • 40
  • 3
    If the statements are `int a=5;int a=10;` at global scope, what will be the final value? It turns out that its a compilation error! – nitish712 Jan 22 '14 at 06:58
  • @Vaibhav any spec for your "merged" concept. I heard about this first time.! – Jeegar Patel Jan 22 '14 at 07:00
  • Its not any specific "merged" concept. It will treat as a single variable declaration when it is Global and as @nitish712 asked if you declare the same variable with different values then it will not work.It works only in case of int a, int a, int a, int a=10. – Vaibhav Jain Jan 22 '14 at 07:03
  • suppose before extern was implemented, if i defined a variable in file 1.c lets call it "int number=10" and then if I use it in file2.c how would have this been implemented, would the variable name "int number" in file2.c simply refer to the variable in file1.c just curious. – tesseract Jan 22 '14 at 07:04
  • 1
    @nitish712 you can have multiple declarations but only 1 definition. – tesseract Jan 22 '14 at 07:08
  • 1
    @VaibhavJain Then for my question, why is it giving me a compilation error? Perhaps you should say `declaration` instead of `definition` as @tesseract pointed out. See [this](http://stackoverflow.com/questions/1410563/what-is-the-difference-between-a-definition-and-a-declaration) – nitish712 Jan 22 '14 at 07:14
  • @nitish712: Agree..!! – Vaibhav Jain Jan 22 '14 at 07:17
  • 3
    The first two sentences in your answer (oddly formatted as code) are misleading. You say multiple definitions are allowed, and that's not true. Assuming the variable has external linkage, multiple definitions are not allowed across multiple translation units, let alone the same one. Now, multiple *tentative* definitions are allowed in the same translation unit (and across multiple ones on most compilers) but when explaining the difference between tentative and non-tentative definitions, you really need to be explicit which one you're talking about. – Praetorian Jan 22 '14 at 07:23