Alsayed Alsisi
Alsayed Alsisi

Reputation: 29

What happens if I define the same variable in each of two .c files without using "extern"?

When I have two .c files as follows:

file1.c:

int x;
//code

main.c:

int x;
int main(){return 0;}

Now, when I compile my program that consists of those two files, in which of the two files is x considered "declaration" and in which is considered "definition"?

Or what exactly happens?

I know that this should be avoided, but I really would like to know how this works.

Upvotes: 1

Views: 677

Answers (3)

H.S.
H.S.

Reputation: 12669

From C Standards#6.2.2p2 Linkages of identifiers:

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.

From C Standards#6.2.2p5 Linkages of identifiers

If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier extern. If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external.

So, if in file.c, you have:

int x;

and main.c also you have:

int x;

Both x will represent the same object and external linkage.

From C Standards#6.2.7.p2

All declarations that refer to the same object or function shall have compatible type; otherwise, the behavior is undefined.

Since you have type of x same in both file. So, if you assign some value to any of them and other will represent the same value but if you assign a value to both x then the linker may throw duplicate symbol error because of multiple definitions of x or you may get undefined behavior.

Multiple external definitions is a common extension referenced in informative Annex J in the C Standards. From C Standards#J.5.11

J.5.11 Multiple external definitions

There may be more than one external definition for the identifier of an object, with or without the explicit use of the keyword extern; if the definitions disagree, or more than one is initialized, the behavior is undefined (6.9.2).

In your case, the definition of x agree, so there is no problem until you are explicitly initializing only one of them.

Upvotes: 1

in which of the two files is x considered "declaration" and in which is considered "definition"?

In both. Each one of those is a "tentative definition". But since it's alone in the file, it's as though you defined x in each. So the two translations units you've shown violate allowed program semantics. To quote n1570 (C11 standard draft, closest to publication), emphasis mine:

6.9.2 External object definitions - Paragraph 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.

6.9 External definitions - Paragraph 5

An external definition is an external declaration that is also a definition of a function (other than an inline definition) or an object. If an identifier declared with external linkage is used in an expression (other than as part of the operand of a sizeof or _Alignof operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for the identifier; otherwise, there shall be no more than one.

You don't use either of the variables in your example, but it's immaterial. You have two definitions, which is more that the zero or one that the standard allows you. As such, your program has undefined behavior when linked. GCC is doing the unkind thing, and letting you build and run your program without a hitch.

Upvotes: 2

Achal
Achal

Reputation: 11921

first file,

xyz@xyz-PC:~/s_flow$ vi main.c
#include<stdio.h>
int x;// this is declaration .. same as extern int x;

int main()
{
        //linker will search definition of x in other file or below this function if you mention extern, not in same function
        printf("printing x value : %d \n",x);
        return 0;
}

2nd file,

xyz@xyz-PC:~/s_flow$ vi file1.c 
int x = 100 ; // this is definition

Explanation I putted in comments inside code.

Upvotes: -1

Related Questions