My project consists of only two source files:
a.cpp:
const int n = 8;
b.cpp:
extern const int n;
int main()
{
// error LNK2001: unresolved external symbol "int const n" (?n##3HB)
int m = n;
}
I know there are several methods to make it work; however, I just wonder WHY it does't work?
It's because const implies internal linkage by default, so
your "definition" isn't visible outside of the translation unit
where it appears.
In this case, by far the best solution is to put the declaration
(extern int const n;) in a header file, and include that in
both a.cpp and b.cpp. The linkage is determined by the
first declaration the compiler sees, so the later definition in
a.cpp will have the correct (external) linkage.
Alternatively, you can force the linkage in the definition:
extern int const n = 8;
Despite the extern, this is still a definition; anything with
an initializer outside of a class definition is a definition.
const and constexpr variables in C++ have internal linkage (and thus aren't accessible in other compilation unit) if they aren't also declared extern (either in the definition or in a previous declaration).
In C, it isn't the case (well C hasn't constexpr) so your code is valid, and more you can put extern on a definition.
So if you want to write code which is both C and C++ (and the two declarations should probably come from the same header as James pointed out):
// a.cpp
extern const int n;
const int n = 8;
// b.cpp
extern const int n;
int main()
{
int m = n;
}
if you don't
// a.cpp
extern const int n = 8;
is also possible
Declare it extern in a.cpp and just use without extern in b.cpp:
a.h
extern const int n ;
a.cpp
#include "a.h"
...
const int n= 8
b.cpp:
#include "a.h"
...
int main()
{
int m = n;
}
To share a const object among multiple files, you must define the variable as extern.
To define a single instance of a const variable, we use the keyword extern on both its definition and declaration(s):
From these rules you just need to add the extern keyword in your definition. you already have it in declaration.
If the other answers here do not do the trick, it may be the case that you have your definitions in different namespaces... if the compilation passes, and you get an undefined symbol linker error:
check the namespace of the undefined symbol; that's the effective namespace for the extern const int n declaration.
ensure that's your effective namespace where you make the const int n = 8 definition.
Related
I realized that I can define an extern variable, like:
source.cpp
extern int i = 42; // definition, can very well just remove the `extern`
main.cpp
#include <iostream>
extern int i; // declaration
int main()
{
std::cout << i << std::endl;
}
I can then compile and link the program,
g++ main.cpp source.cpp
and it runs and correctly displays 42. The warning I get is
warning: 'i' initialized and declared 'extern' (gcc)
warning: 'extern' variable has an initializer (clang)
Using int i = 42; in source.cpp has exactly the same overall effect.
My question: is there any non-trivial use case for variables defined extern (not just declared then defined in another translation unit)? Is such a definition even standard compliant?
The extern specifier is useful in conjunction with variables that would have internal linkage without it, such as constants at namespace scope:
a.cpp:
extern const int n = 10; // external linkage
b.cpp:
int main()
{
extern const int n; // finds the n defined in the other TU
return n;
}
My project consists of only two source files:
a.cpp:
const int n = 8;
b.cpp:
extern const int n;
int main()
{
// error LNK2001: unresolved external symbol "int const n" (?n##3HB)
int m = n;
}
I know there are several methods to make it work; however, I just wonder WHY it does't work?
It's because const implies internal linkage by default, so
your "definition" isn't visible outside of the translation unit
where it appears.
In this case, by far the best solution is to put the declaration
(extern int const n;) in a header file, and include that in
both a.cpp and b.cpp. The linkage is determined by the
first declaration the compiler sees, so the later definition in
a.cpp will have the correct (external) linkage.
Alternatively, you can force the linkage in the definition:
extern int const n = 8;
Despite the extern, this is still a definition; anything with
an initializer outside of a class definition is a definition.
const and constexpr variables in C++ have internal linkage (and thus aren't accessible in other compilation unit) if they aren't also declared extern (either in the definition or in a previous declaration).
In C, it isn't the case (well C hasn't constexpr) so your code is valid, and more you can put extern on a definition.
So if you want to write code which is both C and C++ (and the two declarations should probably come from the same header as James pointed out):
// a.cpp
extern const int n;
const int n = 8;
// b.cpp
extern const int n;
int main()
{
int m = n;
}
if you don't
// a.cpp
extern const int n = 8;
is also possible
Declare it extern in a.cpp and just use without extern in b.cpp:
a.h
extern const int n ;
a.cpp
#include "a.h"
...
const int n= 8
b.cpp:
#include "a.h"
...
int main()
{
int m = n;
}
To share a const object among multiple files, you must define the variable as extern.
To define a single instance of a const variable, we use the keyword extern on both its definition and declaration(s):
From these rules you just need to add the extern keyword in your definition. you already have it in declaration.
If the other answers here do not do the trick, it may be the case that you have your definitions in different namespaces... if the compilation passes, and you get an undefined symbol linker error:
check the namespace of the undefined symbol; that's the effective namespace for the extern const int n declaration.
ensure that's your effective namespace where you make the const int n = 8 definition.
I've encountered many examples on the web, that have extern int x in main.c, where the main function lies.
The only use of extern I'm aware of, is to make a declaration in another file, and use it in another file, after defining it.
Like :
a.h : extern int x;
a.c : int x = 5;
main.c :
#include "a.h" // and start using x
The 1st case seems redundant to me.
So,
Is there any possible use of using an extern variable in a file that is not included in any other file?
extern tells the compiler that x exists in a different module and should be linked from elsewhere. Putting it in main.c directly just avoids pulling in a header (which would be included in-line anyways)
Just like in a header, x still needs to exist in another .c module where it isn't defined extern.
extern variable has basically two functions one is to use the variable in the other file and the other is to access global variables as in the following code.
int x=10;
int main()
{
int x=20;
cout<<x; //refers to x=20
if(x==20)
{
extern int x;
cout<<x; //refers to the global x that is x=10
}
}
Of course. Using extern in a file lets you use that variable in that file. It doesn't have to be included anywhere else.
The use of extern causes the object to have external linkage; to
instantiate a template with a object (and not a value or a type), the
object has to have external linkage (at least in C++03). Most objects
defined in namespace scope have global linkage, but const objects don't.
So you have something like:
template <char const* n>
class Toto { /* ... */ };
char const n1[] = "abc";
Toto<n1> t1; // Illegal...
extern char const n2[] = "xyz";
Toto<n2> t2; // Legal...
It's sort of a special case, but it has led me (once or twice) to use
extern in an unnamed namespace in a source file.
This variable is defined in xyz.cpp
const int i = 10;
The below main() method is written in abc.cpp
void main()
{
cout<<i; //trying to access 'i' from a different .cpp file
}
You need to declare it extern in abc.cpp:
extern const int i;
EDIT: As stated in the comment below, in C++ (unlike C), to give a const variable external linkage, you need to declare it es extern also in xyz.cpp:
extern const int i = 10;
Reference: MSDN
The simplest way is to declare it in a header as const static int i=10; and include that header in all the .cpp that need that constant. This will allow it to be "inlined" by the compiler in every object file, still avoiding ODR violations.
---edit---
Actually, in C++ the static is not required, since const objects have internal linkage by default. But in C, you have to put that static (and in C++ it doesn't hurt).
Why is this better than the extern method? Because:
it's more idiomatic. In C++ you'll always write integral constants in headers as const variables (and that's the very reason why they have internal linkage by default).
it's less typing. You just have to write the const declaration once, then your constants are just a #include away.
it (usually) produces more efficient code. The definition of extern-declared variables cannot be accessed by the compiler when it is producing the current object module, so it cannot optimize it by putting its actual value as an immediate value in the produced machine code, it cannot eliminate branches that cannot be reached with that value of the constant, ... Sure, cross-module optimization ("link time code generation", "whole program optimization", ...) does exist, but at the moment compilers have more advanced optimizers than linkers.
Add the keyword extern in front of it.
Declare it in abc.cpp as:
extern const int i = 10;
const variables in C++ have an internal linkage in C++(unlike C). So to be able to use it in another file you have to explicitly declare it as having external linkage.
Put this global variable into header and #include this header in all .cpp files where you want to use it.
xyz.h:
const int i = 10;
xyz.cpp:
#include "xyz.h"
void main()
{
cout << i;
}
Or if you want to avoid using header for this purpose, you can declare it as extern const int i = 10; in xyz.cpp, but then you have to declare this variable in abc.cpp too, so you should write extern const int i; at the beginning of abc.cpp in order to use it.
The same way as using extern variables.
In the file xyz.cpp:
extern const int i = 333;
In the file abc.cpp:
extern const int i;
cout << i;
I googled const + extern on the internet, but it seems there isn't really a good answer for my question.
const alone means internal linkage, but if I want to share a const variable among compilation units. Is extern the best choice?
Common solution would be:
//g.h
extern const int MAX;
// g.c
extern const int MAX = 3;
However, this solution has a drawback, like below:
// Say, I want to use this MAX in the same header file.
// g.h
extern const int MAX;
class AClass
{
public:
AClass (): i(MAX){}
private:
int i;
};
Compiler will complain like:"error C2057: expected constant expression".
Is there a solution for this?
if you want to be able to use your constant at compile time (i.e. size an array by it, without using VLA) it has to be known at compile time, i.e. it cannot have external linkage.
However, you could just declare your constant in your header file, and make it available to anyone including it. Still, that won't have the exact same effect as an external linkage.
// a.h
const int MAX = 3;
// a.cpp
#include "a.h"
int b[a];
An easy solution for constant integers is to use enums:
// g.h
enum { MAX = 3; }
// g.c
#include "g.h"
static char buf[MAX];
You won't be able to take the address of MAX, but in turn you get this at zero memory cost.
extern const int MAX;
int i[MAX];
Can't be done. You could do something like
const int MAX = ReadAnIntegerFromTheConsole();
Perfectly valid and legal, but whoopsies- not a constant expression.
const alone means internal linkage
This is not correct, static indicates internal linkage, const just says the object cannot mutate. Try declaring a variable as
extern static int foo;
Your compiler will complain about conflicting linkage. To share a const between translation units do exactly what you've suggested.
In the header
extern const int MAX;
In the source file
const int MAX = 10; // note you can omit the extern here
Here is a working example that may solve your issue. In summary, define the array size as a constant in a header file. In another header file declare the array as extern. In the example below I reference the array as extern without using an include file for the array.
array_size.hpp
const unsigned int MAX_ARRAY_SIZE = 16;
array.cpp
#include "array_size.hpp"
int array[MAX_ARRAY_SIZE];
main.cpp
#include "array_size.hpp"
// Reference the array from array.cpp
extern int array[MAX_ARRAY_SIZE];
int main(void)
{
array[1] = 7;
return 0;
}
The *array_size.hpp* file defines the size, the identifier can be used in other translation units by including the header.
I compiled on Cygwin using:
g++ -I. -o array.exe main.cpp array.cpp
Why not just use a #define?
#define MAX 3