Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clarification on Scope and Redefinition [duplicate]

Tags:

c

Referring to the code below:

#include <stdio.h>

int a;
int a;

int main()
{
    int b;
    int b;

    return 0;
}

Why does the compiler (GCC) complain of redeclaration for only variable 'b' and not 'a'?

redef.c: In function 'main': redef.c:19: error: redeclaration of 'b' with no linkage

redef.c:18: error: previous declaration of 'b' was here

like image 843
Prabhu Avatar asked Jan 10 '23 19:01

Prabhu


2 Answers

It's because a has external linkage and the standard states (C11, 6.2.2/2):

An identifier declared in different scopes or in the same scope more than once can be made to refer to the same object or function by a process called linkage. There are three kinds of linkage: external, internal, and none.

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.

So, because a has external linkage, both those declarations refer to the same underlying variable. Because b has no linkage, the declaration refer to unique variables and therefore conflict with each other.

like image 59
paxdiablo Avatar answered Jan 23 '23 11:01

paxdiablo


Quoting the C99 standard §6.9.2 ¶2

A declaration of an identifier for an object that has file scope without an initializer, and without a storage-class specifier or with the storage-class specifier static, constitutes a tentative definition. If a translation unit contains one or more tentative definitions for an identifier, and the translation unit contains no external definition for that identifier, then the behavior is exactly as if the translation unit contains a file scope declaration of that identifier, with the composite type as of the end of the translation unit, with an initializer equal to 0.

Therefore, both the statements

int a;
int a;

constitute tentative definitions. According to the above quoted part, the behaviour is as if the two statements were replaced by

int a = 0;

However, b defined inside main is an automatic variable, i.e., it has automatic storage allocation. There cannot be two definitions of an automatic variable.

like image 42
ajay Avatar answered Jan 23 '23 12:01

ajay