extern const in this particular situation - c++

There are other questions about using extern and const in C++. I also have read about internal and external linkage (it is been a while since I used C++) But I would appreciate if someone reminds to me about the usage of the following particular situation.
I have two cpp files: Description.cpp and Register.cpp and one hpp file: Description. h .They are something like this
//Description.cpp
#include "Description.hpp"
extern const FD models[];
//some other code
.
//Register.cpp
#include "Description.hpp"
extern const FD models[2]={
{"elementA",{1,2}},
{"elementB",{3,4}}
};
.
//Description.hpp
struct FD{
string name;
double v[2];
};
I am wondering why the extern keyword is necessary in Register.cpp

As discussed in the comments, by default, a const object has internal linkage, meaning you can only see it from the file you define it in. To change that, you use the keyword extern, which means "this variable can be seen from other files". Therefore, in Register.cpp, you need extern to tell the linker to make this visible elsewhere, and in Description.cpp you need extern to tell the compiler it might be defined elsewhere.
A better solution would be to move the declaration extern const FD models[]; into a .hpp file (either Description.hpp or a new Register.hpp, depending on details of your project). Then in Description.cpp and any other code that uses models, you include that file and don't need the declaration at all. In Register.cpp, you also include this header. Then the compiler knows that models has external linkage and you don't need to say extern again.

Related

Confused about 'extern' and 'static extern' storage classes in C++11

I read over a few articles about this, and am taking a few introductory courses to C++ concurrently. All of the courses I am taking and these articles just don't help me understand how to implement the extern and static extern storage class. I don't feel comfortable moving on until I really have a grasp on this, even though what I am seeing from other programmers is that they do not use these storage classes, but use inheritance from a header file and local static storage class to use a static variable in a function. Both of those instances I can do. I figured out how to use the static storage class both within the same source file and also by inheriting the static variable from an inherited source file.
I keep getting linker and / or compiler errors.
I am using Visual Studio 2015 Community Edition with C++11, and have CodeDroid in Android with C++98.
Will someone please teach me how to use the extern and static extern storage classes without linker and compiler errors?
For example, say I had one.cpp and two.cpp. Say I have an int main() function in one.cpp. Say I want to demonstrate outputting the value of an extern int in the main() function. And, say I have a void function called extFuncExample() declared and defined in one.cpp, and also want to output its value there.
A course I am taking has extern and static extern as two different storage classes. So, if you would be so kind as to break this down to me, so I can output these values without compiler and linker errors.
Thank you so much!
one.cpp
#include <iostream>
#include "Two.cpp"
int main()
{
extern int global_int;
std::cout << "global_int = " << global_int << '\n';
return 0;
}
two.cpp
#include <iostream>
int global_int = 100;
This, I found works. I was including #include "two.cpp" in one.cpp and also using the extern storage class which was causing the issues. Removed #include "two.cpp" and it worked!
In C and C++ there is a difference between a (forwards) declaration and a definition of symbols. extern is used to forwards declare the existence of a symbol which is external to the translation unit, that is: to 'import' symbol from "somewhere" and "make it visible" to the code being compiled. At link time the references to external symbols are resolved.
Effectively extern is a way to instruct the compiler/toolchain that it should not expect to find the symbol definition among the code being compiled, but instead should look in the libraries being linked against to find it. The linker will not bother to do so for symbols that aren't declared extern.
Apart from that, there is a somewhat common mistake that people make with extern: to use it to declare a global variable and also define it inside a header. For example:
// some header.h
extern int my_global = 40; // = 40 makes this wrong.
Then they proceed to include it multiple times in different translation units (source files):
// file1.c{pp}
#include "header.h"
// file2.c{pp}
#include "header.h"
At this point you have introduced multiple definitions for the same symbol in your program because #include simply copies the contents of the header verbatim into the context at which the #include is performed. The compiler will still compile the code, but the linker will refuse to link it because of the multiple definition error.

How can I use a global variable in C++?

I'm developping a Blackberry 10 mobile app. using the momentics IDE (BB Native SDK).
In my application, I want to use global variables that will be shared by many classes.
I tried the code below like described in this link, but when I add the extern instruction before the declaration of the variable "g_nValue* " in the ".h" file, it returns the error "storage class specified for 'g_nValue'"
*/ global.cpp:
// declaration of g_nValue
int g_nValue = 5;
*/ global.h:
#ifndef GLOBAL_H // header guards
#define GLOBAL_H
// extern tells the compiler this variable is declared elsewhere
extern int g_nValue;
#endif
Any one have an idea on this? I searched a lot and they all said that the extern instruction should not cause any trouble.
An alternative to extern are static variables inside a class:
//.h
struct Globals
{
static int g_global_var;
};
//.cpp
int Globals::g_global_var = 0;
//usage:
Globals::g_global_var;
the extern qualifier only tells the compiler, "this symbol is defined in a different source file" - so the symbol exists, it's safe to use it. You will get a linking error if you actually "lie" about it and don't define the symbol - but that's a different story.
There does not seam to be any problem with the code you showed us.
But here is a link which might help you get a better idea...
You don't declare the variable exteren in the compilation unit it's defined in. You only declare it extern (and don't define it) if you want to use it in other .cpp files (compilation units).
Your code seems fine. Maybe the you have an error elsewhere. Maybe there is a semicolon (;) missing in a line before extern int g_nValue.

Duplicate symbol error associated with const char * [] declaration

I'd love help diagnosing the source of a duplicate symbol error that I'm receiving when I try to compile with g++ 4.2.1.
The specific error is
ld: duplicate symbol _SOCIODEM_FILENAMES in /var/folders/c+/c+eq1Qz1Feye7vxs5mQOUE+++TI/-Tmp-//ccP3yVgF.o and /var/folders/c+/c+eq1Qz1Feye7vxs5mQOUE+++TI/-Tmp-//cc1NqtRL.o
collect2: ld returned 1 exit status
The error occurs only when I include this declaration in a file called Parameters.h:
// Parameters.h
#ifndef PARAMETERS_H
#define PARAMETERS_H
// ...[code snipped]...
const int NUM_SOCIODEM_FILES = 5;
const char * SOCIODEM_FILENAMES[ NUM_SOCIODEM_FILES ] = { "LSPAN_PDF.txt",
"FLEDGE_PDF.txt",
"PAIR_PDF.txt",
"BIRTH_AGE_PDF.txt",
"SPLIT_PDF.txt" };
// ...[code snipped]...
#endif
I've searched all my files, and this is the only place where SOCIODEM_FILENAMES is declared. When I comment out the declaration, the 'duplicate symbol' error goes away.
I'm unfamiliar with linker errors (if that's what this is) and would appreciate help troubleshooting the problem. All my header files have #ifndef...#define...#endif wrappers. My compile command is
g++ -o a.out -I /Applications/boost_1_42_0/ Host.cpp Simulation.cpp main.cpp Rdraws.cpp
Thanks in advance.
Solution summary
I now have in Parameters.h:
const char * const SOCIODEM_FILENAMES[ NUM_SOCIODEM_FILES ] = { "LSPAN_PDF.txt",
"FLEDGE_PDF.txt",
"PAIR_PDF.txt",
"BIRTH_AGE_PDF.txt",
"SPLIT_PDF.txt" };
All other definitions and declarations in Parameters.h are unchanged. Andrey and other commenters summarize an alternative approach using extern, which is overkill for my purposes.
For some reason none of the answers so far cared to explain the difference between your integer NUM_SOCIODEM_FILES object and array SOCIODEM_FILENAMES object. The latter triggers the linker error for the reasons already explained: because you include you header file into multiple implementation files. Yet, the former would link without any problems (because there are indeed no problems with NUM_SOCIODEM_FILES declaration). Why?
The reason for this is that your NUM_SOCIODEM_FILES object is declared const. In C++ const objects have internal linkage by default, meaning that they do not cause linking problems even if they are defined in multiple implementation files. In other words, in C++ your NUM_SOCIODEM_FILES is equivalent to
static const int NUM_SOCIODEM_FILES = 5; /* internal linkage */
which is why it does not lead to any linking problems.
At the same time your SOCIODEM_FILENAMES is not declared constant, which is why it gets external linkage by default and eventually leads to linker errors. But if you declare your SOCIODEM_FILENAMES as const as well, the problem will go away
const char * const SOCIODEM_FILENAMES[ NUM_SOCIODEM_FILES ] = {
...
Note where the extra const is placed in the declaration. If you just add that extra const and leave everything else as is (i.e. keep the definition if SOCIODEM_FILENAMES in the header file), the linker will not report the error even if you include your header file into multiple translation units.
This is not a recommended approach though, since that way you will give your SOCIODEM_FILENAMES internal linkage and end up with a standalone copy of SOCIODEM_FILENAMES array in each translation unit - something that might work fine but still makes very little sense. So, for your array, it is normally better to use the extern approach recommended in other answers.
However, note that you shouldn't normally do it for NUM_SOCIODEM_FILES declaration!!! It is fine as it is, defined in the header file. Unless you are trying to do something unusual, scalar constants should normally be defined with initializer in the header files - that way they can be seen as compile-time constants in all translation units, which is a rather valuable thing to have. So, beware of the strange advice present in some other answers to move the definition of NUM_SOCIODEM_FILES into .cpp file as well - this actually makes no sense and is a totally wrong thing to do.
Most likely, you are #includeing this file in multiple source files. The problem is that each inclusion results in a separate definition for a variable named SOCIODEM_FILENAMES. Include guards do not help with this. Include guards prevent multiple declarations within a single compilation unit; they do not prevent multiple definitions across several compilation units.
What you need to do is declare these variables as extern in the header, and then define them in exactly one source file. e.g.
// Parameters.h
#ifndef PARAMETERS_H
#define PARAMETERS_H
// ...[code snipped]...
extern const int NUM_SOCIODEM_FILES;
extern const char * SOCIODEM_FILENAMES[];
// ...[code snipped]...
#endif
and then:
// Parameters.cpp (or some other source file)
const int NUM_SOCIODEM_FILES = 5;
const char * SOCIODEM_FILENAMES[ NUM_SOCIODEM_FILES ] = { "LSPAN_PDF.txt",
"FLEDGE_PDF.txt",
"PAIR_PDF.txt",
"BIRTH_AGE_PDF.txt",
"SPLIT_PDF.txt" };
You can get away with not doing this for the int because it is a constant integer, and so the compiler can just treat it as a compile-time constant, and it will never even show up in the compiled code. However, the char* cannot be treated this way, and so must have exactly one definition (known as the "one definition rule" in C++).
The header guard (#ifndef..#endif wrapper) just prevents you from including the same header multiple times in a single source file. You can still have multiple source files that include that header, and each one will declare that symbol separately. Since they all have the same name, linking those sources together will cause a symbol name collision. You probably want to declare the symbol in a source file instead of a header file
The problem is you are putting a definition in a header file. If you include that file in more than one compilation unit (.cpp file) you will be in effect creating multiple definitions and at link time you will get that error.
You need to put both those definitions in a .cpp file and put only a declaration in the header file:
extern const int NUM_SOCIODEM_FILES;
extern const char * SOCIODEM_FILENAMES[];
As others have suggested, one way of doing this is to declare NUM_SOCIODEM_FILES and SOCIODEM_FILENAMES as extern and define them once in an external file. The other way is to declare them as static--this causes them to be duplicated in every object file that includes the header, but will not create an error since the definition is private to that object file. Which option you choose is entirely up to your own preferences.

Is it appropriate to set a value to a "const char *" in the header file

I have seen people using 2 methods to declare and define char *.
Medhod 1: The header file has the below
extern const char* COUNTRY_NAME_USA = "USA";
Medhod 2:
The header file has the below declaration:
extern const char* COUNTRY_NAME_USA;
The cpp file has the below definition:
extern const char* COUNTRY_NAME_USA = "USA";
Is method 1 wrong in some way ?
What is the difference between the two ?
I understand the difference between "const char * const var" , and "const char * var". If in the above methods if a "const char * const var" is declared and defined in the header as in method 1 will it make sense ?
The first method is indeed wrong, since it makes a definition of an object COUNTRY_NAME_USA with external linkage in the header file. Once that header file gets included into more than one translation unit, the One Definition Rule (ODR) gets violated. The code will fail to compile (more precisely, it will fail to link).
The second method is the correct one. The keyword extern is optional in the definition though, i.e. in the cpp file you can just do
const char* COUNTRY_NAME_USA = "USA"
assuming the declaration from the header file precedes this definition in this translation unit.
Also, I'd guess that since the object name is capitalized, it is probably intended to be a constant. If so, then it should be declared/defined as const char* const COUNTRY_NAME_USA (note the extra const).
Finally, taking that last detail into account, you can just define your constant as
const char* const COUNTRY_NAME_USA = "USA"; // no `extern`!
in the header file. Since it is a constant now, it has internal linkage by default, meaning that there is no ODR violation even if the header file is included into several translation units. In this case you get a separate COUNTRY_NAME_USA lvalue in each translation unit (while in extern method you get one for the entire program). Only you know what you need in your case .
What's the point?
If you want to lookup strings (that could be localized), this would be best:
namespace CountryNames {
const char* const US = "USA";
};
Since the pointer is const, it now has internal linkage and won't cause multiple definitions. Most linkers will also combine redundant constants, so you won't waste space in the executable.
If you want to compare strings by pointer equality though, the above isn't portable because the pointers will only be equal if the linker performs the constant-folding optimization. In that case declaring an extern pointer in the header file is the way to go (and it again should be const if you don't intend to retarget it).
If you must have global variables, normal practice is to declare them in a .h file and define them in one (and only one) .cpp file.
In a .h file;
extern int x;
In a .cpp file;
int x=3;
I have used int (the most fundamental basic type perhaps?) rather than const char * as in your example because the essence of your problem doesn't depend on the type of variable.
The basic idea is that you can declare a variable multiple times, so each .cpp file that includes the .h file declares the variable, and that is fine. But you only define it once. The definition is the statement where you assign the variables initial value, (with an =). You don't want definitions in .h files, because then if the .h file is included by multiple .cpp files, you'll get multiple definitions. If you have multiple definitions of one variable, there is a problem at link time because the linker wants to assign the address of the variable and cannot reasonably do that if there are multiple copies of it.
Additional information added later to try and ease Sud's confusion;
Try to reduce your problem to it's minimal parts to understand it better;
Imagine you have a program that comprises three .cpp files. To build the program each .cpp is compiled separately to create three object files, then the three object files are linked together. If the three .cpp files are as follows (example A, good organization);
file1.cpp
extern int x;
file2.cpp
extern int x;
file3.cpp
extern int x;
Then the files will compile and link together without problem (at least as far as the variable x is concerned). There is no problem because each file is only declaring variable x. A declaration is simply stating that there is a variable out there somewhere that I may (or may not) use.
A better way of achieving the same thing is the following (example A, better organization);
header.h
extern int x;
file1.cpp
#include "header.h"
file2.cpp
#include "header.h"
file3.cpp
#include "header.h"
This is effectively exactly the same, for each of the three compilations the compiler sees the same text as earlier as it processes the .cpp file (or translation unit as the experts call it), because the #include directive simply pulls text from another file. Nevertheless this is an improvement on the earlier example simply because we only have our declaration in one file, not in multiple files.
Now consider another working example (example B, good organization);
file1.cpp
extern int x;
file2.cpp
extern int x;
file3.cpp
extern int x;
int x=3;
This will work fine as well. All three .cpp files declare x and one actually defines it. We could go ahead and add more code within functions in any of the three files that manipulates variable x and we wouldn't get any errors. Again we should use a header file so that the declaration only goes into one physical file (example B, better organization).
header.h
extern int x;
file1.cpp
#include "header.h"
file2.cpp
#include "header.h"
file3.cpp
#include "header.h"
int x=3;
Finally consider an example that just wouldn't work (example C, doesn't work);
file1.cpp
int x=3;
file2.cpp
int x=3;
file3.cpp
int x=3;
Each file would compile without problems. The problem occurs at link time because now we have defined three separate int x variables. The have the same name and are all globally visible. The linker's job is to pull all the objects required for a single program into one executable. Globally visible objects must have a unique name, so that the linker can put a single copy of the object at one defined address (place) in the executable and allow all the other objects to access it at that address. The linker cannot do it's job with global variable x in this case and so will choke out an error instead.
As an aside giving the different definitions different initial values doesn't address the problem. Preceding each definition with the keyword static does address the problem because now the variables are not globally visible, but rather visible within the .cpp file that the are defined in.
If you put a global variable definition into a header file, nothing essential has changed (example C, header organization not helpful in this case);
header.h
int x=3; // Don't put this in a .h file, causes multiple definition link error
file1.cpp
#include "header.h"
file2.cpp
#include "header.h"
file3.cpp
#include "header.h"
Phew, I hope someone reads this and gets some benefit from it. Sometimes the questioner is crying out for a simple explanation in terms of basic concepts not an advanced computer scientist's explanation.

Is this extern harmless?

main.h
extern int array[100];
main.c
#include "main.h"
int array[100] = {0};
int main(void)
{
/* do_stuff_with_array */
}
In the main.c module, the array is defined, and declared. Does the act of also having the extern statement included in the module, cause any problems?
I have always visualized the extern statement as a command to the linker to "look elsewhere for the actual named entity. It's not in here.
What am I missing?
Thanks.
Evil.
The correct interpretation of extern is that you tell something to the compiler. You tell the compiler that, despite not being present right now, the variable declared will somehow be found by the linker (typically in another object (file)). The linker will then be the lucky guy to find everything and put it together, whether you had some extern declarations or not.
To avoid exposure of names (variables, functions, ..) outside of a specific object (file), you would have to use static.
yea, it's harmless. In fact, I would say that this is a pretty standard way to do what you want.
As you know, it just means that any .c file that includes main.h will also be able to see array and access it.
Edit
In both C and C++, the presence of extern indicates that the first declaration is not a definition. Therefore, it just makes the name available in the current translation unit (anyone who includes the header) and indicates that the object referred to has external linkage - i.e. is available across all the translation units making up the program. It's not saying that the object is necessarily located in another translation unit - just that 'this line isn't the definition'.
End edit
In C, the extern is optional. Without it, the first declaration is a 'tentative definition'. If it were not for the later definition (which is unambiguously a definition because it has an initializer), this would be treated as a definition (C99 6.9.2). As it is, it's just a declaration and does not conflict.
In C++, the extern is not optional - without it, the first declaration is a definition (C++03 3.1) which conflicts with the second.
This difference is explicitly pointed out in Annex C of C++:
"Change: C++ does not have “tentative definitions” as in C
E.g., at file scope,
int i;
int i;
is valid in C, invalid in C++."
The extern is harmless and correct. You couldn't declare it in the header without extern.
As an extra, usually it is best practice to create a macro or a constant to hold the size of the array; in your code the actual size (100) appears twice in the source base. It would be cleaner to do it like this:
#define ARRAY_SIZE 100
extern int array[ARRAY_SIZE];
...
int array[ARRAY_SIZE] = { 0 };
But maybe you did not want to include this in the code snippet just for the sake of brevity, so please take no offense :)
From a compilation or execution point of view, it makes no difference.
However, it's potentially dangerous as it makes array[] available to any other file which #includes main.h, which could result in the contents of array[] being changed in another file.
So, if array[] will only ever be used in main.c, remove the line from main.h, and declare array[] as static in main.c.
If array[] will only be used in the main() function, declare it in there.
In other words, array[] should have its scope limited to the smallest possible.