2

I have this code - http://ideone.com/8Q8XIo

#include <stdio.h>

int xyz = 10;
int main(void) {

    int xyz = 20;//line 2
    printf("%d",xyz);

    return 0;
}

My question is - Why doesn't it give redeclaration error? I know that second time its in 'main' function's scope. But I think doing just xyz = 20 in 'line 2' is fine but not int xyz = 20.

pmr
  • 58,701
  • 10
  • 113
  • 156
halkujabra
  • 2,844
  • 3
  • 25
  • 35
  • 3
    Because you're not redeclaring anything. – user657267 Nov 10 '14 at 12:00
  • 4
    This is not an error - you're just shadowing the global - if you enable warnings though then a good compiler will helpfully point this out to you. See: http://stackoverflow.com/questions/19155514/same-variable-as-global-and-local-in-c – Paul R Nov 10 '14 at 12:00
  • 1
    For instance it's handled by `-Wshadow` option in both GCC and Clang. – Grzegorz Szpetkowski Nov 10 '14 at 12:05

5 Answers5

4

C scope rule says that, when a declaration inside a block names an identifier that's already visible, the new declaration temporarily hides the old one, and the identifier takes on a new meaning.
At the end of the block, the identifier regains its old meaning.

C11: 6.2.1 Scopes of identifiers (p4):

[...] If an identifier designates two different entities in the same name space, the scopes might overlap. If so, the scope of one entity (the inner scope) will end strictly before the scope of the other entity (the outer scope). Within the inner scope, the identifier designates the entity declared in the inner scope; the entity declared in the outer scope is hidden (and not visible) within the inner scope.

Community
  • 1
  • 1
haccks
  • 104,019
  • 25
  • 176
  • 264
4

According to the C Standard (6.2.1 Scopes of identifiers)

  1. ...Within the inner scope, the identifier designates the entity declared in the inner scope; the entity declared in the outer scope is hidden (and not visible) within the inner scope.

In your example the first declared identifier

int xyz = 10;

has file scope. The second declared identifier

int xyz = 20;//line 2

has block scope that is enclosed in the file scope. That is the block scope is an inner scope relative to the file scope. The second declared identifier hides the first declared identifier inside the block scope.

The same is valid for C++. Only C++ has namespaces and using a qualified name you can access a hidden variale. For example

#include <iostream>

int xyz = 10;

int main() {

    int xyz = 20;//line 2

    std::cout << "xyz = " << xyz << ", ::xyz = " << ::xyz << std::endl;

    return 0;
}

Here :: before xyz denotes the global namespace.

Take into account that you could also use the same name for a function parameter declaration in a function declaration. For example

void f( int xyz );

In this case this identifier has function prototype scope. Also you could even to declare a lable with the same name as for example

In C

xyz:;
int xyz = 20;

or in C++

xyz:
int xyz = 20;

Also in C tags have its own namespace. So this declaration is valid in C

xyz:;

struct xyz
{
   int xyz;
};

int xyz = 20;
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
2

Why doesn't it give redeclaration error?

Because it is not a redeclaration. You're declaring a new local variable. Since it has the same name as one in the global scope, it hides that one, but that's it. It is perfectly legal C.

Mat
  • 202,337
  • 40
  • 393
  • 406
1

It does not give a re-declaration error because they are in different scopes. The first declaration is in the global scope and the second one is in the local scope(only valid in main).

Shwetha
  • 150
  • 7
0

Why doesn't it give redeclaration error?

Because (as others said) while this is a redeclaration, it is not an error case, as long as the two variables are in different scopes.

Difference:

int f() {
    int x = 0;
    int x = 1; // same scope, this will not compile (redeclaration error)
}

int g() {
    int x = 0;
    {
        int x = 1; // inner scope, no conflict at all
        std::cout << x << "\n"; // print 1
    }
    std::cout << x << "\n"; // print 0
}
utnapistim
  • 26,809
  • 3
  • 46
  • 82