user103214
user103214

Reputation: 3658

Why "int i" has multiple definitions?

I have two files as below:

Test1.h

#ifndef TEST_H
#define TEST_H

int i = 10;

#endif

Test2.cpp

#include <iostream>

#include "Test1.h"

int main()
{
    std::cout << i << std::endl;
}

I know I can solve this by using extern or const in Test1.h.

But my question is that "I don't understand the error".

error LNK2005: "int i" (?i@@3HA) already defined in Test1.obj
error LNK1169: one or more multiply defined symbols found

How can int i have multiple definitions?

  1. The header file has include guards.
  2. When I include the header file it should mean that everything gets copied in Test2.cppand it should become:

Test2.cpp

#include <iostream>

int i = 10

int main()
{
    std::cout << i << std::endl;
}

And header file should become irrelevant at this point after everything being included.

My other question is if I declare int i with extern in header file and include it in .cpp, then would it be an example of external linkage? Because generally I have seen external linkage between two .c or .cpp as in here but if you explicitly include the file is it still regarded as i having external linkage?

Upvotes: 1

Views: 309

Answers (5)

Van Tr
Van Tr

Reputation: 6103

Do you have other Test1.cpp in your project that also include the Test1.h ?

If not, do you do any config to your compiler so it also build the .h files to object files ?

The reason can just be the answer of one of two questions above.

Upvotes: 0

eerorika
eerorika

Reputation: 238321

How can int i have multiple definitions?

The file that has the definition was included in multiple translation units (cpp file). One unit was compiled into the object file Test1.obj. The source of the other unit is shown in your answer (Test2.cpp). The error is shown when you try to link the object files together.

  1. The header file has include guards.

That prevents the contents of the file from being repeated within a single translation unit. It makes no difference to separate units.

My other question is if I declare int i with extern in header file and include it in .cpp, then would it be an example of external linkage?

extern makes the linkage external explicitly. But even without extern, variables declared in the namespace scope have implicit external linkage by default (there are exceptions). The difference in this case is that extern variable declarations are not definitions unless there is an initializer.

I can achieve external linkage without including header file i.e. with two .cpp files by making a variable extern in one .cpp and defining it in other and linker finds its definition. But if I have one header file with extern variable and include it in other .cpp does this count as external linkage?

It does not matter how the extern declaration ends up in the cpp file. Whether it was included from a header or not, it declares a variable with external linkage.

Upvotes: 1

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385144

When I include the header file it should mean that everything gets copied in Test2.cpp and it should become:

Yes and then you do the exact same thing in Test1.cpp (which you didn't show us).

Hence, multiple definitions.

Upvotes: -1

CashCow
CashCow

Reputation: 31435

Each compilation unit (a .cpp file) produces its own set of symbols individually which are then linked together by the linker.

A header file "becomes" part of the compilation unit it is included in, which compile to an object file (.obj in Windows, .o in Unix systems)

Therefore it is like you have defined a global 'i' in each compilation unit. The correct solution (as you know, if you have to have a global) is to declare it as "extern" in the header then have one compilation unit actually define it.

Include guards only prevent the same header being included twice in the same compilation unit, which can happen if I include and and one of those includes the other.

Upvotes: 3

EFenix
EFenix

Reputation: 831

Probably you are trying to create the executable file from two unit of translations.

Your error shows that the object have been defined in Test1.obj. Probably, your program is Test1.obj+Test2.obj, and both files include the same definition, which has external linkage.

Upvotes: 1

Related Questions