This question already has answers here:
What is the effect of extern "C" in C++?
(17 answers)
When to use extern in C++
(4 answers)
Closed 8 years ago.
So I am trying to understand it and what it is used for, I get the difference between a declared and defined variable.
I'll try to explain what I am confused at using the examples in the tutorial.
Example 1:
extern int var;
int main(void)
{
var = 10;
return 0;
}
so here I get that you cannot assign var to 10 because no memory was allocated to it.
Example 2:
#include "somefile.h"
extern int var;
int main(void)
{
var = 10;
return 0;
}
I'm lost here. somefile.h would have something like int var = 0;to declare it correct? ut then why would this program declare it again?
Obligatory point #1: this relates to global variables, so the first thing you really need/want to do is not learn how to use them, but how to avoid them. They're much more likely to lead to problems than a solution.
That said, at least in the usual case, you put an extern declaration in a header. You put the definition of the variable in one source file, and you include the header in any other file that needs access to that variable.
For example:
//file1.cpp:
int var;
Then the header that declares the variable:
//file1.h:
extern int var;
Then in one file that needs access to the variable:
#include "file1.h"
int main() {
var = 10; // Yes, this *is* allowed
}
...and in another file that needs access to the variable:
#include "file1.h"
int f() { return var; }
I'll repeat though: this is almost never necessary or desirable. If you're actually using globals very often at all, you're probably doing something wrong (I make it a practice to use a global once a year so I don't forget how, but it's been at least a few years since I used any other than that).
Basically the extern keyword tells the compiler/linker that it should expect the variable to be instantiated and defined elsewhere in the program, for example a library you are linking to or whatever object file "somefile.h" compiles to. Extern lets the compielr and programmer "know" about a variable while letting another piece of code actually manage it.
Here is a good explanation of extern:
https://stackoverflow.com/a/496476/1874323
extern effectively means that somewhere, in all the linked obj files/libraries there exists a variable (in your case) called "var of type int, the compiler doesn't know where, but he'll let the linker find it for you". This keeps the compiler happy.
In your case, you're right, 'int var=1;' must be defined somewhere, actually, in a c\cpp file, not a header (if it was in a header, you wouldn't need to extern it, you could just #include it).
If you extern a variable, but don't define it somewhere, the linker will get unhappy - with an unresolved symbol error (i.e. its saying "you told me to look for a variable called 'var', but I can't find it).
So - theoretically, you should not be able to create an executable with an extern'd variable which isn't defined.
Related
I know global is bad but just as a practice, is this the correct way to initialize a global class used between multiple object files?
Header 1.h
class test {
int id;
public:
test(int in){
id = in;
}
int getId(){
return id;
}
};
extern test t;
File 1.cc:
#include <iostream>
#include "1.h"
int main(){
std::cout << t.getId() << std::endl;
return 0;
}
File 2.cc:
#include "1.h"
test t(5);
Now what if instead of extern I use the static approach globally static test t(0); in the header?
Correct me if I'm wrong but that would compile fine however I would have 2 different unrelated copies of the same t in both object files and the final binary? Is that bad? Or does the linker sort it out to eliminate multiple copies?
There are global instances, not global classes.
What you have is a global instance. And yes, this sounds about right, until you get to multiple global instances which depend upon each other. Then the real fun will start.
Defining a variable as 'static' at global level means the variable will be defined in the compilation unit only (i.e. the '.o' file) and the symbol won't be exported by the compiler.
In other words: yes, there will be multiple variables with the same name but only visible to functions on the same compilation unit.
Besides, 'invisible' doesn't mean 'inaccessible'. You still can provide access to the variable. For example:
1.h
struct Test { int value; }; // Class definition
Test& get_t(); // Function declaration
1.cc
#include "1.h"
static Test t; // Variable declared as 'static'
Test& get_t() { return t; };
2.cc
#include "1.h"
#include <iostream>
int main()
{
std::cout << get_t().value << std::endl; // Static variable accessed
}
I use the static approach globally static test t;?
But your test class needs an int in parameter for the constructor, so you want:
static test t(0); // or whatever int you want
If you turn the extern to static in the header, you would define a static variable in each compilation unit in which the header is imported. So classes in different cpp files would no longer "communicate" via t, since each would have theirs. This is very error prone.
In addition, adding the definition of a static in a header is an extremely bad practice. When someone includes a header, one does not expect that it will create variables.
Including the declaration of t as extern is an acceptable practice. But be aware that if the header has a general purpose, this might reduce its reusability other projects.
More information of interest for you:
Must read: C++ Core Guidelines about source files
Must read: Guidelines for writing headers
StackOverflow: When are global variables recommended
Why global variables should be avoided if possible and when are they ok
If you put a variable declaration outside of any function, you're declaring the variable as 'global'. Ex:
1.cc
int this_is_global;
From here on you can use the variable in any function of '1.cc'.
For using the same variable in any other file, the compiler will need to know about it:
2.cc
extern int this_is_global;
Here, the keyword extern tells the compiler that the variable is declare somewhere else, letting the task of finding it to the linker.
If you miss to add the extern keyword here, the compiler will treat it as a new variable, and the linker will have two variables with the same name and will emit an error. All of your source files of your project except the first one will need the extern keyword to avoid duplicate symbols.
So common practice is to add the 'extern' declaration in an include file:
1.cc
int this_is_global;
1.h
extern int this_is_global;
2.cc
#include "1.h"
On the other side, the static keyword tells the compiler not to export the symbol. In other words: the variable will exists only in the source file it is declared. You could declare it once per source file and there will be different variables with the same name. Ex:
1.h
static int my_var;
1.cc
#include "1.h"
2.cc
#include "1.h"
This way, you'll end having two variables 'my_var' and changes to any of them won't affect the other.
This is the most confusing part for me from section Global Variables and linkage properties.
extern int g_var1;
Statement could be something like this when defining an external non-const global variable. I think I will write exactly the same for using that variable (through forward-declaration) in some other file. If both the statements are same, how C++ knows whether the variable was declared or was defined in a file?
If I understand your question correctly, you shouldn't write exactly the same in another file (namely, you shouldn't write "extern int g_var1" in two files). A good practice is to declare some variable global in a header file; make the definition in a cpp file that includes this header file. After doing this, you can use this variable in all of the files that will include the header file.
To illustrate, an example would be something like this:
variables.hpp
#pragma once
extern int g_var1;
variables.cpp
#include "variables.h"
int g_var1 = 1;
main.cpp
#include "variables.h"
#include <iostream>
using namespace std;
int main(){
cout << g_var1 << endl;
}
A statement of the form
extern int g_var1; // this is a declaration
is a declaration of a variable. The keyword extern makes sure of this.
If you write
int g_var1; // declare and define variable
you define it as well. You can declare a variable as many times as you like, but define it only once. You could therefore write
extern int g_var1;
in those files where you need to use the variable. Then during linking the compiler will resolve the definition of the variable (provided that you give the definition in some file of course).
When you say extern int g_var1; the variable is just declared, and later when you have to use it you can use it directly.
file1.cpp:
int g_var1;
File2.cpp:
extern int g_var1;
You need not to write extern everytime.
Though i would suggest if you have to use global variables place them in a separate header file.
My C++ program needs to use an external C library.
Therefore, I'm using the
extern "C"
{
#include <library_header.h>
}
syntax for every module I need to use.
It worked fine until now.
A module is using the this name for some variables in one of its header file.
The C library itself is compiling fine because, from what I know, this has never been a keyword in C.
But despite my usage of the extern "C" syntax,
I'm getting errors from my C++ program when I include that header file.
If I rename every this in that C library header file with something like _this,
everything seems to work fine.
The question is:
Shouldn't the extern "C" syntax be enough for backward compatibility,
at least at syntax level, for an header file?
Is this an issue with the compiler?
Shouldn't the extern "C" syntax be enough for backward compatibility, at least at syntax level, for an header file? Is this an issue with the compiler?
No. Extern "C" is for linking - specifically the policy used for generated symbol names ("name mangling") and the calling convention (what assembly will be generated to call an API and stack parameter values) - not compilation.
The problem you have is not limited to the this keyword. In our current code base, we are porting some code to C++ and we have constructs like these:
struct Something {
char *value;
char class[20]; // <-- bad bad code!
};
This works fine in C code, but (like you) we are forced to rename to be able to compile as C++.
Strangely enough, many compilers don't forcibly disallow keyword redefinition through the preprocessor:
#include <iostream>
// temporary redefinition to compile code abusing the "this" keyword
#define cppThis this
#define this thisFunction
int this() {
return 1020;
}
int that() {
return this();
}
// put the C++ definition back so you can use it
#undef this
#define this cppThis
struct DumpThat {
int dump() {
std::cout << that();
}
DumpThat() {
this->dump();
}
};
int main ()
{
DumpThat dt;
}
So if you're up against a wall, that could let you compile a file written to C assumptions that you cannot change.
It will not--however--allow you to get a linker name of "this". There might be linkers that let you do some kind of remapping of names to help avoid collisions. A side-effect of that might be they allow you to say thisFunction -> this, and not have a problem with the right hand side of the mapping being a keyword.
In any case...the better answer if you can change it is...change it!
If extern "C" allowed you to use C++ keywords as symbols, the compiler would have to resolve them somehow outside of the extern "C" sections. For example:
extern "C" {
int * this; //global variable
typedef int class;
}
int MyClass::MyFunction() { return *this; } //what does this mean?
//MyClass could have a cast operator
class MyOtherClass; //forward declaration or a typedef'ed int?
Could you be more explicit about "using the this name for some variables in one of its header files"?
Is it really a variable or is it a parameter in a function prototype?
If it is the latter, you don't have a real problem because C (and C++) prototypes identify parameters by position (and type) and the names are optional. You could have a different version of the prototype, eg:
#ifdef __cplusplus
extern "C" {
void aFunc(int);
}
#else
void aFunc(int this);
#endif
Remember there is nothing magic about header files - they just provide code which is lexically included in at the point of #include - as if you copied and pasted them in.
So you can have your own copy of a library header which does tricks like the above, just becoming a maintenance issue to ensure you track what happens in the original header. If this was likely to become an issue, add a script as a build step which runs a diff against the original and ensures the only point of difference is your workaround code.
I don't know what this problem belong to , Just please spend your time to read. It involves a difference about C and C++ and a habit of writing code; the code is as follows:
I divide it into 3 files;
the main.c
#include"myh.h"
unit_t *paa;
int main()
{
paa=(unit_t*)malloc(sizeof(unit_t));
if(paa==NULL){
printf("out of memory\n");
exit(1);
}
fuzhi(paa);
printf("hello !%d",paa->number);
free(paa->msg);
free(paa);
paa=NULL;
return 0;
}
anohter c: ke.c
#include"myh.h"
void fuzhi(unit_t* pa)
{
pa->number=3;
pa->msg=(char *)malloc(20);
printf("fuzhi !");
}
the h file: myh.h
#ifndef P_H
#define P_H
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct{
int number;
char *msg;
}unit_t;
void fuzhi(unit_t* pa);
int a;
#endif
So the problem is when I run the code using C it has no problem ,but when I save it as cpp, the error is multiple definiton of 'a'; why?
The second question is I don't know the habit I arrange the code is good or not. Is someone give me some good advice? When the code is big , I usually put the declaration in the h file and use a c/cpp the write the definition of the function. Then use a main c/cpp to meet the main function. Can someone give me some good advice about writing code, I am a new learner.
Thanks.
The first thing you have to remember is that C and C++ are different languages, and so have different rules about globally declared variables. And you do have the global variable a defined multiple times: Once in the main.c file and once in the ke.c file.
This is because you define the variable in the header file, which you include in both your source files. What you should do is declare the variable in the header file, and then define it in a single source file.
For example, in the header file you should have
extern int a;
And in one source file:
int a;
The compilation process as follows:
For each c. or .cpp file (called compilands):
preprocess the file, resolving all macros, #includes, etc...
compile the file, producing the object file .o. Object file contains machine code, but non-local variables are still referenced by names.
Then at the end link all object files, which includes:
resolving all the non-local variable names
replacing those with addresses
In your case, you have two compilands: main.c and ke.c.
During preprocessing, both include the .h file. As a result, both compilands declare a global variable int a. Each compiland uses its own copy of that global variable.
Then, the linker tries to resolve the names and is surprised seeing two object files defining two variables under the same name.
To solve it, in C++ header you use the keyword "extern":
extern int a;
This indicates that there will be a global variable a, but it not defines it (similarly to a function declaration without definition). In one of the compilands you then need to repeat the normal int a definition, but in a place that is not seen by other compilands (that is - not in a header)
Sorry for this type of question. But, I am very curious about the keyword extern in C\C++.
while searching for explanation for extern I got to know that extern tell the compiler that the variable or function is already defined in some other file or program.
But if this is a case then why we use extern?
as I tried some codes as follows:
extern int var;
int main(void)
{
var = 10;
return 0;
}
This code is giving me an error message as unresolved external symbol "int var" (?var##3HA).
and if I am using some code like:
extern int var;
int main(void)
{
int var = 10;
return 0;
}
It is not showing any error and gives value same as I have defined in main function.
So, Can any one help me about the behavior of extern?
I am little confused on this.
Please forgive me if it is not a valid question.
Thank you in Advance.
extern is used to refer to a variable in another translation unit ("source file").
For instance, your code in main.c looks like this:
extern int var;
int main(void)
{
var = 10;
return 0;
}
This code contains a declaration for an integer named var, but no definition, because extern explicitly says: "the definition for this is somewhere else"
You could define another source file, say, other.c:
int var = 0;
Then, after you add this new translation unit to your build command, your program will link fine, and the code in both files can operate on the shared var variable.
In the second version, you just override the declaration of the extern var with a local variable in your main function. Since the extern var is not (ODR-)used anymore, the linker does not require it, so your executable can build successfully.
The first version fails since you must also provide a definition of the extern-declared variable, i.e. by linking with some other C file that has
int var;
in its global scope.
The second one succeeds since the int var = 10; line in main() shadows the global declaration; this is generally a bad thing to be doing if you wanted the variable to be extern, i.e. shared among many C files. Of course, such sharing in itself is often quite bad too (see: global variables).
extern is used to indicate that a variable exists in another compilation unit. If you had:
main.cpp
extern int var;
int main(void)
{
var = 10;
return 0;
}
and:
var.cpp
int var;
Then you wouldn't have got the linker error as the linker would have hooked up the use of var in main.cpp with it's decleration in var.cpp
In your second example you've defined an extern int var but you never reference it. The int var = 10 is a completely different int var from the extern one. When they linker runs it notices that you never use the extern int var variable so doesn't bother to search for it.
I would suggest you must clear your understanding of definition and declaration of variable.
extern keyword is used when you want to say that the variable was allocated memory you want only to declare the variable.
When you declare the any variable using extern keyword compiler will try to find the definition of the same variable which can be present before or after declaration.
In the first case you are just declaring the variable not assigning it any memory i.e not defining variable.
you can go through this for better understanding of extern keyword.
If you have declared a global variable, let's say double myvar=5 in file1.cpp and you want to access that variable in file2.cpp, then in your file2.cpp you declare as
extern double myvar;
In C++, each file is called a compilation unit. For the file to be compiled to an object file, you need all variables declared however you do not need to initialize or do an assignment on those variables.
Returning to the example:
File1.cpp: double myvar=5 this is both a declaration and initialization. You can compile file1.cpp to file1.o.
File2.cpp: Assuming that you are using myvar somewhere in file2.cpp and also you want to access the value (maybe after a calculation) in file1.cpp. Therefore, in order to be able to compile file2.cpp into file2.o, you must declare extern double myvar, so that file2.cpp can be compiled. This will please the compiler and leaves the task to linker.
Now that you have compiled these files, you will have object files (translation units) named as (if you are using g++) file1.o and file2.o. Now it is linker's job to link them together and let file2.o to access myvar.
Declaring a variable extern tells the compiler that the actual instance of the variable is somewhere else. If you don't provide it somewhere else, the link stage will fail.
In your second example you don't refer to the extern declared variable at all. You declare a new one in the scope of your main function that shadows the global declaration.