access const variables accross translation units - c++

In C++, const variables are implicitly hidden from other translation units. Is is possible to prevent that?

Yes, prefix the definition with extern eg.
extern const int x = 10;

Use the extern keyword:
extern const int x = 10;
This forces the variable to have external linkage.
For namespace-scope variables this is usually the default, and you'd use static (or, better, an anonymous namespace) to force internal linkage.
I didn't actually know that namespace-scope const variables have internal linkage by default until I read your question and tried it out, so thanks for that. Learn something new every day!

It can be achieved by means of the extern keyword:
// a.cpp
extern const int x = 10; // definition
// b.cpp
extern const int x; // declaration
The effect this will have is that you will not need to recompile b if the value of the constant changes in a, but at the same time you loose the ability to use x as a compile time constant inside b.cpp (i.e. you will not be able to write int array[x];).
If there isn't a very strong reason for this, I would rather have the constant defined in a header file and included in all translation units that require it;
// c.h
const int x = 10;
// a.cpp
#include "c.h"
// b.cpp
#include "c.h"
You will have to recompile all translation units that depend on the constant with each change, but you will be able to use it at compile time in all translation units. The limitation of this approach is that if you change the constant and only recompile some of the translation units, the value of the constant will be inconsistent (this is a violation of the ODR).

Related

static global std::unique_ptr disappears

I probably misunderstood how static objects work. Suppose following
common.hpp
struct common {};
static std::unique_ptr<common> global_ptr;
foo.cpp
#include "common.hpp"
void bar();
int main()
{
global_ptr = std::make_unique<common>();
bar();
}
bar.cpp
#include "common.hpp"
void bar()
{
*global_ptr; // crashes, because global_ptr is empty
}
I am able to debug such situation, and &global_ptr is different in main() and bar(), why is that? global_ptr is definitely initialized in main(), I can use it without problem, but why global_ptr in bar() seems unitialized?
static variable at global and namespace scope means internal linkage.
The name can be referred to from all scopes in the current translation unit.
It means global_ptr in different translation unit are different objects. The static variable is not visible outside of its own translation unit. There might be many objects with the name global_ptr, but only one per translation unit.
If you just want a global variable, you could declare it in common.hpp as:
extern std::unique_ptr<common> global_ptr;
and define it in the cpp file (might be common.cpp):
std::unique_ptr<common> global_ptr;
Globals behave like your intended behavior without the static keyword.
Static means that the global is actually local to the translation unit.
Your confusion comes from the fact that static means different things in global scope and in function scope.

Is extern keyword required here, const in cpp file

If I have in header file
namespace Bob
{
extern const T x;
};
And in source file
extern const T Bob::x = 123;
Is the second extern in the source file required or optional?
I've searched and found conflicting information.
From this webpage:
http://msdn.microsoft.com/en-us/library/357syhfh.aspx
But to get the same behavior in C++, you must declare your const variable [in source file] as:
extern const int i = 2;
Usually, the extern keyword tells the compiler not to define a symbol, because it will be defined somewhere else. So writing e.g.
namespace Bob {
extern T x;
}
does not define the variable x, but rather declares it. You can have as many extern declarations as you like. However, if you do not provide a definition the linking will fail. So you have to define
T Bob::x;
somewhere in the code in order to provide the definition.
The const keyword is a little special here, because it implies internal linkage. This means, that the definition of x will not be visible outside the specific compilation unit where it was defined. To alter this behavior you do need to write
extern const T Bob::x = 123;
if you want x to be const and also reference it from other compilation units.
----yet another edit----
Just to be absolutely clear:
If a const variable is supposed to be referenced outside of its compilation unit, then you must explicitly declare it extern.
However, if the declaration is given separately from the definition, then the definition does not necessarily need to specify the keyword extern again. Yet another example for demonstration:
myheader.h
extern const int i;
This declares i a const integer with external linkage, but does not define it.
main.cpp, version 1
#include "myheader.h" //Through the include, the above declaration of `i` comes before its definition.
const int i=123; // Although the `extern` modifier is omitted here,
// it's still in effect because we already declared `i` as `extern`
// Therefore it makes no difference here, whether or not you specify `extern` again.
// The compiler knows this is a definition either way, because of the initialization.
main.cpp, version 2
//#include "myheader.h"
extern const int i=123; // this line is declaration and definition in one, because we did not include
// the declaration from myheader.h. Thus, to tell the compiler that you want
// `i` with external linkage, you MUST specify `extern`. Otherwise you'll get
// internal linkage.
I hope all this now makes sense to you.
You can control the linkage of a symbol with the static and extern keywords. The default linkage is extern for non-const symbols and static (i.e. internal) for const symbols at namespace scope. This is valid for C++ but not for C (where you would have to declare it as static to make it have internal linkage).
So if you have
const int i = 2;
into a .c file and you use it into another unit by declaring
extern const int i;
that's fine in C since that variable has external linkage by default (and with the extern keyword you're instructing the compiler to find it into another unit), but in C++ the same
const int i = 2;
into a .cpp file (firmstanding what I wrote) has internal linkage and it would have to be defined with
extern const int i = 2;
to explicitly have external linkage and be able to be used into another unit with
extern const int i;
Finally when you initialize a global variable you're always defining it in the module where you're doing it, this means that the following is perfectly valid:
#include <iostream>
using namespace std;
#define T int
extern const T x; // This is a declaration
extern const T x = 123; // This is a definition
int main() {
std::cout << x; // 123
return 0;
}
That means the second 'extern' keyword is also unnecessary.

How to declare a global variable in C++

I know one should not use global variables but I have a need for them. I have read that any variable declared outside a function is a global variable. I have done so, but in another *.cpp file, that variable could not be found. So it was not really global. Isn't it so that one has to create a header file GlobalVariabels.h and include that file to any other *cpp file that uses it?
I have read that any variable declared outside a function is a global variable. I have done so, but in another *.cpp File that variable could not be found. So it was not realy global.
According to the concept of scope, your variable is global. However, what you've read/understood is overly-simplified.
Possibility 1
Perhaps you forgot to declare the variable in the other translation unit (TU). Here's an example:
a.cpp
int x = 5; // declaration and definition of my global variable
b.cpp
// I want to use `x` here, too.
// But I need b.cpp to know that it exists, first:
extern int x; // declaration (not definition)
void foo() {
cout << x; // OK
}
Typically you'd place extern int x; in a header file that gets included into b.cpp, and also into any other TU that ends up needing to use x.
Possibility 2
Additionally, it's possible that the variable has internal linkage, meaning that it's not exposed across translation units. This will be the case by default if the variable is marked const ([C++11: 3.5/3]):
a.cpp
const int x = 5; // file-`static` by default, because `const`
b.cpp
extern const int x; // says there's a `x` that we can use somewhere...
void foo() {
cout << x; // ... but actually there isn't. So, linker error.
}
You could fix this by applying extern to the definition, too:
a.cpp
extern const int x = 5;
This whole malarky is roughly equivalent to the mess you go through making functions visible/usable across TU boundaries, but with some differences in how you go about it.
You declare the variable as extern in a common header:
//globals.h
extern int x;
And define it in an implementation file.
//globals.cpp
int x = 1337;
You can then include the header everywhere you need access to it.
I suggest you also wrap the variable inside a namespace.
In addition to other answers here, if the value is an integral constant, a public enum in a class or struct will work. A variable - constant or otherwise - at the root of a namespace is another option, or a static public member of a class or struct is a third option.
MyClass::eSomeConst (enum)
MyNamespace::nSomeValue
MyStruct::nSomeValue (static)
Declare extern int x; in file.h.
And define int x; only in one cpp file.cpp.
Not sure if this is correct in any sense but this seems to work for me.
someHeader.h
inline int someVar;
I don't have linking/multiple definition issues and it "just works"... ;- )
It's quite handy for "quick" tests... Try to avoid global vars tho, because every says so... ;- )

Can anyone explain this portion of the C++0x draft standard?

From ISO Standard Draft: ยง3.0/9:
n3234 says:
A name used in more than one translation unit can potentially refer to the
same entity in these translationunits depending on the linkage (3.5) of the
name specified in each translation unit.
Can anyone explain this point with an example, please?
What is that statement actually saying? Can any one prove this point in terms of a program?
Sure! What this is saying is that if you have multiple source files (translation units) that both use some name (for example, the name of a variable, class or function), then it's possible that those different files are talking about the same variable, class, or function, assuming that that entity was declared in a way that makes it visible across different files (that is, depending on its linkage).
For example, if I have this file:
A.cpp:
int globalInt;
int main() {
globalInt = 137;
}
And this one here:
B.cpp:
extern int globalInt;
void foo() {
globalInt = 42;
}
Then in both files, the name globalInt refers to the global int variable globalInt defined in A.cpp. That's all that this point is saying.
Note, however, that if I declare globalInt without external linkage, then the two files will be talking about different variables. For example, in this case:
C.cpp:
static int globalInt;
int main() {
globalInt = 137;
}
D.cpp:
static int globalInt;
void foo() {
globalInt = 42;
}
Now the globalInt variable referenced in C.cpp is not the same as the one in D.cpp, even though they have the same name.
Hope this helps!
Ah, standards... let's obfuscate the obvious.
It's saying that, if you use a global variable with the same name in two different source files, they will be the same variable if they are extern or don't specify at all, but if any of them are declared static then those will be completely independent because they're only visible in that source file.
int a; // can be seen in other files; this may be duplicated in multiple source files
static int b; // can only be used in this file
extern int c; // explicitly using a visible variable "c" defined in another file
("Linkage" is the static/extern/default global, or auto which is almost never mentioned since it means "allocated on the stack", which is the default for variables declared inside a function and obviously not meaningful for a declaration outside a function. "Translation unit" is a common way for standards to avoid mentioning "files".)

What does 'const static' mean in C and C++?

const static int foo = 42;
I saw this in some code here on StackOverflow and I couldn't figure out what it does. Then I saw some confused answers on other forums. My best guess is that it's used in C to hide the constant foo from other modules. Is this correct? If so, why would anyone use it in a C++ context where you can just make it private?
A lot of people gave the basic answer but nobody pointed out that in C++ const defaults to static at namespace level (and some gave wrong information). See the C++98 standard section 3.5.3.
First some background:
Translation unit: A source file after the pre-processor (recursively) included all its include files.
Static linkage: A symbol is only available within its translation unit.
External linkage: A symbol is available from other translation units.
At namespace level
This includes the global namespace aka global variables.
static const int sci = 0; // sci is explicitly static
const int ci = 1; // ci is implicitly static
extern const int eci = 2; // eci is explicitly extern
extern int ei = 3; // ei is explicitly extern
int i = 4; // i is implicitly extern
static int si = 5; // si is explicitly static
At function level
static means the value is maintained between function calls.
The semantics of function static variables is similar to global variables in that they reside in the program's data-segment (and not the stack or the heap), see this question for more details about static variables' lifetime.
At class level
static means the value is shared between all instances of the class and const means it doesn't change.
It has uses in both C and C++.
As you guessed, the static part limits its scope to that compilation unit. It also provides for static initialization. const just tells the compiler to not let anybody modify it. This variable is either put in the data or bss segment depending on the architecture, and might be in memory marked read-only.
All that is how C treats these variables (or how C++ treats namespace variables). In C++, a member marked static is shared by all instances of a given class. Whether it's private or not doesn't affect the fact that one variable is shared by multiple instances. Having const on there will warn you if any code would try to modify that.
If it was strictly private, then each instance of the class would get its own version (optimizer notwithstanding).
That line of code can actually appear in several different contexts and alghough it behaves approximately the same, there are small differences.
Namespace Scope
// foo.h
static const int i = 0;
'i' will be visible in every translation unit that includes the header. However, unless you actually use the address of the object (for example. '&i'), I'm pretty sure that the compiler will treat 'i' simply as a type safe 0. Where two more more translation units take the '&i' then the address will be different for each translation unit.
// foo.cc
static const int i = 0;
'i' has internal linkage, and so cannot be referred to from outside of this translation unit. However, again unless you use its address it will most likely be treated as a type-safe 0.
One thing worth pointing out, is that the following declaration:
const int i1 = 0;
is exactly the same as static const int i = 0. A variable in a namespace declared with const and not explicitly declared with extern is implicitly static. If you think about this, it was the intention of the C++ committee to allow const variables to be declared in header files without always needing the static keyword to avoid breaking the ODR.
Class Scope
class A {
public:
static const int i = 0;
};
In the above example, the standard explicitly specifies that 'i' does not need to be defined if its address is not required. In other words if you only use 'i' as a type-safe 0 then the compiler will not define it. One difference between the class and namespace versions is that the address of 'i' (if used in two ore more translation units) will be the same for the class member. Where the address is used, you must have a definition for it:
// a.h
class A {
public:
static const int i = 0;
};
// a.cc
#include "a.h"
const int A::i; // Definition so that we can take the address
It's a small space optimization.
When you say
const int foo = 42;
You're not defining a constant, but creating a read-only variable. The compiler is smart enough to use 42 whenever it sees foo, but it will also allocate space in the initialized data area for it. This is done because, as defined, foo has external linkage. Another compilation unit can say:
extern const int foo;
To get access to its value. That's not a good practice since that compilation unit has no idea what the value of foo is. It just knows it's a const int and has to reload the value from memory whenever it is used.
Now, by declaring that it is static:
static const int foo = 42;
The compiler can do its usual optimization, but it can also say "hey, nobody outside this compilation unit can see foo and I know it's always 42 so there is no need to allocate any space for it."
I should also note that in C++, the preferred way to prevent names from escaping the current compilation unit is to use an anonymous namespace:
namespace {
const int foo = 42; // same as static definition above
}
It's missing an 'int'. It should be:
const static int foo = 42;
In C and C++, it declares an integer constant with local file scope of value 42.
Why 42? If you don't already know (and it's hard to believe you don't), it's a refernce to the Answer to Life, the Universe, and Everything.
C++17 inline variables
If you Googled "C++ const static", then this is very likely what you really want to use are C++17 inline variables.
This awesome C++17 feature allow us to:
conveniently use just a single memory address for each constant
store it as a constexpr: How to declare constexpr extern?
do it in a single line from one header
main.cpp
#include <cassert>
#include "notmain.hpp"
int main() {
// Both files see the same memory address.
assert(&notmain_i == notmain_func());
assert(notmain_i == 42);
}
notmain.hpp
#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP
inline constexpr int notmain_i = 42;
const int* notmain_func();
#endif
notmain.cpp
#include "notmain.hpp"
const int* notmain_func() {
return &notmain_i;
}
Compile and run:
g++ -c -o notmain.o -std=c++17 -Wall -Wextra -pedantic notmain.cpp
g++ -c -o main.o -std=c++17 -Wall -Wextra -pedantic main.cpp
g++ -o main -std=c++17 -Wall -Wextra -pedantic main.o notmain.o
./main
GitHub upstream.
See also: How do inline variables work?
C++ standard on inline variables
The C++ standard guarantees that the addresses will be the same. C++17 N4659 standard draft
10.1.6 "The inline specifier":
6 An inline function or variable with external linkage shall have the same address in all translation units.
cppreference https://en.cppreference.com/w/cpp/language/inline explains that if static is not given, then it has external linkage.
GCC inline variable implementation
We can observe how it is implemented with:
nm main.o notmain.o
which contains:
main.o:
U _GLOBAL_OFFSET_TABLE_
U _Z12notmain_funcv
0000000000000028 r _ZZ4mainE19__PRETTY_FUNCTION__
U __assert_fail
0000000000000000 T main
0000000000000000 u notmain_i
notmain.o:
0000000000000000 T _Z12notmain_funcv
0000000000000000 u notmain_i
and man nm says about u:
"u" The symbol is a unique global symbol. This is a GNU extension to the standard set of ELF symbol bindings. For such a symbol the dynamic linker will make sure that in the entire process
there is just one symbol with this name and type in use.
so we see that there is a dedicated ELF extension for this.
Pre-C++ 17: extern const
Before C++ 17, and in C, we can achieve a very similar effect with an extern const, which will lead to a single memory location being used.
The downsides over inline are:
it is not possible to make the variable constexpr with this technique, only inline allows that: How to declare constexpr extern?
it is less elegant as you have to declare and define the variable separately in the header and cpp file
main.cpp
#include <cassert>
#include "notmain.hpp"
int main() {
// Both files see the same memory address.
assert(&notmain_i == notmain_func());
assert(notmain_i == 42);
}
notmain.cpp
#include "notmain.hpp"
const int notmain_i = 42;
const int* notmain_func() {
return &notmain_i;
}
notmain.hpp
#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP
extern const int notmain_i;
const int* notmain_func();
#endif
GitHub upstream.
Pre-C++17 header only alternatives
These are not as good as the extern solution, but they work and only take up a single memory location:
A constexpr function, because constexpr implies inline and inline allows (forces) the definition to appear on every translation unit:
constexpr int shared_inline_constexpr() { return 42; }
and I bet that any decent compiler will inline the call.
You can also use a const or constexpr static variable as in:
#include <iostream>
struct MyClass {
static constexpr int i = 42;
};
int main() {
std::cout << MyClass::i << std::endl;
// undefined reference to `MyClass::i'
//std::cout << &MyClass::i << std::endl;
}
but you can't do things like taking its address, or else it becomes odr-used, see also: Defining constexpr static data members
C
In C the situation is the same as C++ pre C++ 17, I've uploaded an example at: What does "static" mean in C?
The only difference is that in C++, const implies static for globals, but it does not in C: C++ semantics of `static const` vs `const`
Any way to fully inline it?
TODO: is there any way to fully inline the variable, without using any memory at all?
Much like what the preprocessor does.
This would require somehow:
forbidding or detecting if the address of the variable is taken
add that information to the ELF object files, and let LTO optimize it up
Related:
C++11 enum with class members and constexpr link-time optimization
Tested in Ubuntu 18.10, GCC 8.2.0.
According to C99/GNU99 specification:
static
is storage-class specifier
objects of file level scope by default has external linkage
objects of file level scope with static specifier has internal linkage
const
is type-qualifier (is a part of type)
keyword applied to immediate left instance - i.e.
MyObj const * myVar; - unqualified pointer to const qualified object type
MyObj * const myVar; - const qualified pointer to unqualified object type
Leftmost usage - applied to the object type, not variable
const MyObj * myVar; - unqualified pointer to const qualified object type
THUS:
static NSString * const myVar; - constant pointer to immutable string with internal linkage.
Absence of the static keyword will make variable name global and might lead to name conflicts within the application.
In C++,
static const int foo = 42;
is the preferred way to define & use constants. I.e. use this rather than
#define foo 42
because it doesn't subvert the type-safety system.
To all the great answers, I want to add a small detail:
If You write plugins (e.g. DLLs or .so libraries to be loaded by a CAD system), then static is a life saver that avoids name collisions like this one:
The CAD system loads a plugin A, which has a "const int foo = 42;" in it.
The system loads a plugin B, which has "const int foo = 23;" in it.
As a result, plugin B will use the value 42 for foo, because the plugin loader will realize, that there is already a "foo" with external linkage.
Even worse: Step 3 may behave differently depending on compiler optimization, plugin load mechanism, etc.
I had this issue once with two helper functions (same name, different behaviour) in two plugins. Declaring them static solved the problem.
Yes, it hides a variable in a module from other modules. In C++, I use it when I don't want/need to change a .h file that will trigger an unnecessary rebuild of other files. Also, I put the static first:
static const int foo = 42;
Also, depending on its use, the compiler won't even allocate storage for it and simply "inline" the value where it's used. Without the static, the compiler can't assume it's not being used elsewhere and can't inline.
This ia s global constant visible/accessible only in the compilation module (.cpp file). BTW using static for this purpose is deprecated. Better use an anonymous namespace and an enum:
namespace
{
enum
{
foo = 42
};
}
Making it private would still mean it appears in the header. I tend to use "the weakest" way that works. See this classic article by Scott Meyers: http://www.ddj.com/cpp/184401197 (it's about functions, but can be applied here as well).