10

In the following code, why do multiple declarations (and one definition) work fine for a global variable x but not for a local variable y which is inside the main() function? It shows the following 2 errors:

1) redeclaration of 'y' with no linkage

2) previous declaration of 'y' was here

Why is it showing error for the local variable but not global variable? Not only my book, but the following 2 links from this forum clearly state that we can declare a variable multiple times (though define only once).

link1 link2

And kindly take care to explain what does the "with no linkage" part of the first error "redeclaration of 'y' with no linkage" mean? What linkage and to whom? Where would a local variable be linked?

    #include<stdio.h>

    int x;
    int x;
    int x=303;

    int main(void)
    {

      int y;
      int y;
      int y=776;   //Works fine if above 2 declarations are removed!!

      printf("The value of x is %d,and of y is %d",x,y);

    }
wrhall
  • 1,228
  • 1
  • 11
  • 25
Rüppell's Vulture
  • 3,453
  • 7
  • 33
  • 47
  • Read http://en.wikipedia.org/wiki/Linker_%28computing%29 about linkage & linker. And also Levine's book http://www.iecc.com/linker/ ; so local variables are not linked (because they are in the local call frame, on the stack). – Basile Starynkevitch Mar 31 '13 at 21:28
  • But it showing error for x also in my compiler. – Jeyamaran Sep 23 '14 at 09:47
  • @Jeyamaran you may have been using a C++ compiler. This is a C question. – M.M Feb 28 '16 at 00:53

3 Answers3

22

In C and C++, int y; within a function is both a declaration and a definition.

In C, int x; in the file scope (outside any function) is a declaration and a tentative defintion. Multiple tentative definitions are allowed; only one definition is allowed.

maditya
  • 7,816
  • 1
  • 24
  • 27
  • Seems like you hit the bull's eye.Let's wait a while and see what others have to say. – Rüppell's Vulture Mar 31 '13 at 21:44
  • Sure. While we're here, another interesting thing is how scoping affects variable names: http://stackoverflow.com/questions/2393458/why-does-using-the-same-count-variable-name-in-nested-for-loops-work – maditya Apr 01 '13 at 06:42
  • @maditya: What if I declare and define a variable in function (local scope) and not use it? Still memory is allocated? But in case of global scope is memory is allocated only if it is used? – Jon Wheelock Oct 10 '15 at 14:40
  • Also usage of extern means only declaration? What about the usage "extern int x=10;" ? Is it valid and allocates memory as well even if it is not used? – Jon Wheelock Oct 10 '15 at 14:46
  • Tentative definitions are definitions . You are allowed multiple definitions so long as all (or all-but-one) are tentative. What you mean to say in the last sentence is that only one definition with an initializer is allowed. – M.M Feb 28 '16 at 00:52
5

This is the way defined in the C99 standard, section 6.2.2, part 2:

In the set of translation units and libraries that constitutes an entire program, each declaration of a particular identifier with external linkage denotes the same object or function. Within one translation unit, each declaration of an identifier with internal linkage denotes the same object or function. Each declaration of an identifier with no linkage denotes a unique entity.

The "global" variables x have external linkage, so they denote the same object. The local y variables, on the other hand, has no linkage, so there is a collision.

References: C99 Standard.

Sergey Kalinichenko
  • 675,664
  • 71
  • 998
  • 1,399
4

With external variables, any declaration that isn't an initialisation is a tentative definition. These by themselves don't create any storage, so multiple ones are allowed. So taking your example:

int x;      // tentative def
int x;      // and again -- ok
int x=303;  // definition -- ok
int x=303;  // multiple definition -- error

If at the end of the file there have been only tentative definitions, the variable is defined once, and set to 0.

This means that if you link to another file which also has a tentative definition of x, you'll have an error according to the standard. Most compilers/linkers have always allowed this, though, and it's defined in the standard as an extension.

With local variables, each declaration is a definition because of scope rules. This, however, is allowed:

void func(void)
{
   int y = 0;
   {
      int y = 1;   // a completely different y
   }
}
teppic
  • 7,611
  • 1
  • 19
  • 35
  • "This means that if you link to another file which also has a tentative definition of x, you'll have an error according to the standard." I tried this, but there is no error. – Rivers Shall Oct 11 '18 at 02:32