1

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.

1
  • 1
    Both are definitions. It is not legal in C but your compiler/linker may let you get away with it by merging the two definitions into one. Commented Nov 12, 2017 at 10:00

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Note that the C standard allows multiple external definitions as Common Extension and many compilers implement this feature.
C standard allows lots of kinds of behaviour, like division by zero that always results in 42.
1

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.

4 Comments

In fact it is not defined by standard. But some compilers can process that way.
I think it's worth being clear that annex J, section J.5 describes "Common Extensions" and the whole annex is merely "informative".
@CharlesBailey: Thanks. Incorporated your suggestion.
With GCC, the behavior can be controlled with -fno-common (the default is -fcommon). Compling the code from the question with -fno-common produces a "multiple definition of x" error.
-1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.