541

I'm reading "Think in C++" and it just introduced the extern declaration. For example:

extern int x;
extern float y;

I think I understand the meaning (declaration without definition), but I wonder when it proves useful.

Can someone provide an example?

sdgfsdh
  • 33,689
  • 26
  • 132
  • 245
Aslan986
  • 9,984
  • 11
  • 44
  • 75
  • 1
    I've had to provide a definition with `extern` on several occasions. Microsoft tools produced a link error for missing symbols when the tables in another source file were only defined. The problem was, the table was `const` and the C++ compiler promoted it to `static` in the translation unit. See, for example, [`ariatab.cpp`](https://github.com/noloader/cryptopp/blob/master/ariatab.cpp) and [`kalynatab.cpp`](https://github.com/noloader/cryptopp/blob/master/kalynatab.cpp). – jww Aug 12 '17 at 06:43
  • 4
    And I think Nik's answer is the correct one because he's the only one who appears to have answered a C++ question. Everyone else appears to have digressed to a C question. – jww Aug 12 '17 at 06:56
  • 4
    As of C++17, `inline` may be a better way to accomplish what you want to do with `extern`. With `inline`, you can define globals in headers and not worry about multiple definition problems. https://stackoverflow.com/questions/38043442/how-do-inline-variables-work – Joshua Jurgensmeier Nov 19 '20 at 20:28

4 Answers4

717

This comes in useful when you have global variables. You declare the existence of global variables in a header, so that each source file that includes the header knows about it, but you only need to “define” it once in one of your source files.

To clarify, using extern int x; tells the compiler that an object of type int called x exists somewhere. It's not the compilers job to know where it exists, it just needs to know the type and name so it knows how to use it. Once all of the source files have been compiled, the linker will resolve all of the references of x to the one definition that it finds in one of the compiled source files. For it to work, the definition of the x variable needs to have what's called “external linkage”, which basically means that it needs to be declared outside of a function (at what's usually called “the file scope”) and without the static keyword.

header:

#ifndef HEADER_H
#define HEADER_H

// any source file that includes this will be able to use "global_x"
extern int global_x;

void print_global_x();

#endif

source 1:

#include "header.h"

// since global_x still needs to be defined somewhere,
// we define it (for example) in this source file
int global_x;

int main()
{
    //set global_x here:
    global_x = 5;

    print_global_x();
}

source 2:

#include <iostream>
#include "header.h"

void print_global_x()
{
    //print global_x here:
    std::cout << global_x << std::endl;
}
Semnodime
  • 1,872
  • 1
  • 15
  • 24
dreamlax
  • 93,976
  • 29
  • 161
  • 209
  • 26
    Thank you. So, if i declare a global variable in an header file without the extern keyword, the source files that include the header does not see it? – Aslan986 May 02 '12 at 21:42
  • 38
    you should not declare global vars in a header, because then when 2 files include the same header file, it won't link (linker will emit an error about "duplicate symbol") – kuba May 02 '12 at 21:44
  • 92
    @Aslan986: No, something worse happens. Each source file that includes the header will have *its own* variable, so each source file will compile independently but the linker will complain because two source files will have the same global identifiers. – dreamlax May 02 '12 at 21:46
  • 2
    @kuba: you mean declare or define? – Aslan986 May 02 '12 at 21:51
  • 11
    When you don't use the word "extern", then now the variable exists. When you use "extern", it's a "hey there is this var somewhere else". Sorry about not answering whether it's a definition or declaration, since I always get confused about these two. – kuba May 02 '12 at 21:55
  • @Zac this is a trivial example to demonstrate how one would use `extern`. As it is, the answer is factually correct and the example code compiles without warnings. Rather than downvoting, why not edit the answer to improve it? – dreamlax Mar 16 '15 at 21:27
  • @dreamlax, I tried to edit your answer adding include guards, but it was rejected as "This edit deviates from the original intent of the post" (×2) and "This edit does not make the post even a little bit easier to read", so I'm sorry it must remain as is. – Zac Mar 17 '15 at 15:28
  • @Zac then by the consensus of others (including the existing 60 upvotes), there is nothing wrong with this answer. – dreamlax Mar 17 '15 at 21:20
  • 1
    @Zac I concede :) no harm in putting it there – dreamlax Mar 18 '15 at 08:59
  • Since multiple declarations of a variable is allowed but there must be only one definition of it, can I define my variable in the header file (e.g. `int global_x;`) and declare it in all source files (e.g.; `extern int global_x;`) from which I want to have access to it? – hkBattousai Apr 07 '16 at 13:40
  • 2
    @Aslan986 if you "declare a global variable in an header file without the extern keyword" you are defining it and not declaring it. :) – Pedro Reis Oct 06 '16 at 13:00
  • 2
    @dreamlax can you please explain with a code what would happen if we use static modifier? – alamin Dec 28 '16 at 13:08
  • In the answer isn't `extern` supposed to be in the cpp files and the definition without `extern` - in the header? In *Source1* isn't `int global_x` hiding the one in the header? – mireazma Dec 23 '17 at 15:25
  • @mireazma, no that's incorrect. Read the description again. – dreamlax Feb 21 '18 at 00:26
  • re: your answer to @Aslan986, why don't include guards prevent the multiple definition linker issue? – CCJ Jun 18 '18 at 21:57
  • 5
    @CCJ: the include guard only works for the source file that is including it. It stops the same header being included twice within the same source file (just in case other headers also include it etc). So even with include guards, each source file that includes the header will still have its own definition. – dreamlax Jun 20 '18 at 00:23
  • In most other language, definition and declaration finish in one statement. – g10guang Aug 20 '18 at 08:41
  • Actually I believe the standard refers to what you call _function scope_ to _namespace scope_ – Pablo Arias Jan 08 '19 at 17:48
252

It is useful when you share a variable between a few modules. You define it in one module, and use extern in the others.

For example:

in file1.cpp:

int global_int = 1;

in file2.cpp:

extern int global_int;
//in some function
cout << "global_int = " << global_int;
MByD
  • 135,866
  • 28
  • 264
  • 277
  • 63
    This answer is more correct than the accepted one, as it does not make use of header file and it states clearly that it is useful only when sharing between few modules. For larger applications is better to use for example a ConfigManager class. – Zac Mar 16 '15 at 14:53
  • 2
    Is there any gotchas when namespaces are involved, `global_int` is in the global namespace, if I were to use it in file2.cpp in some namespace section I'd have to scope it correct? ie `namespace XYZ{ void foo(){ ::global_int++ } };` – jxramos Sep 29 '15 at 23:53
  • 12
    @Zac: On the other hand, by not declaring a global variable in a header, you've inadvertently made it much more difficult to determine where it is actually defined. Usually if you see a global variable declared in `abc.h`, there's a good chance it'll be defined in `abc.cpp`. A good IDE will always help, but well-organised code is always a better solution. – dreamlax Nov 05 '15 at 21:35
  • without `extern` in file2.cpp , still can access to `global_int` after include. why i need to have it? – TomSawyer Apr 26 '20 at 19:32
  • @TomSawyer you don't want to include in this case. file1.cpp and file2.cpp are supposed to be different compilation units. It would be very uncommon practice to include a .cpp file. – Daniel Bauer Oct 30 '20 at 09:19
  • Adding to @dreamlax 's comment, also you don't want to look at CPP files to know the API to program against. Ideally that would be implementation details to the users of the module. – pooya13 Jan 03 '21 at 05:45
  • Can we use this approach for sharing function as well? – Md. Jan 25 '21 at 06:11
97

It's all about the linkage.

The previous answers provided good explanations about extern.

But I want to add an important point.

You ask about extern in C++, not in C and I don't know why there is no answer mentioning the case when extern comes with const in C++.

In C++, a const variable has internal linkage by default (not like C).

So this scenario will lead to linking error:

Source 1 :

const int global = 255; //wrong way to make a definition of global const variable in C++

Source 2 :

extern const int global; //declaration

It needs to be like this:

Source 1 :

extern const int global = 255; //a definition of global const variable in C++

Source 2 :

extern const int global; //declaration
Brambor
  • 604
  • 1
  • 8
  • 25
Van Tr
  • 5,889
  • 2
  • 20
  • 44
  • 3
    Why it's a wrong while it works in c++ without include 'extern' in the definition part ? – iartist93 Nov 17 '16 at 19:17
  • 1
    I don't seem to encounter that linking error in VIsual Studio with Visual Micro. What am I missing? – Craig.Feied Aug 18 '17 at 03:44
  • 1
    @lartist93 @Craig.Feied I believe you may need to check again carefully. Even in case compiler does not inform linking error, could you check that both objects in both source are same without `extern` in definition ? You could do that by printing out the value of `global` in source 2. – Van Tr May 21 '18 at 01:15
  • 5
    Confirm, in MSVS 2018 there *is* a linking error if `extern` is omitted in `const int global = 255;`. – Evg Sep 01 '18 at 13:14
  • I've seen `extern` used in C++ server code where the client is written in C. I always figured it was done to expose the C++ function to C which wouldn't otherwise be able to link to it. Is this correct ? – wbg Jan 20 '22 at 16:59
  • 1
    @wbg if the two programs communicate through some network protocol then the languages used almost always doesn't matter. If the server-client is similar to functional calls, then most likely `extern "C"` would be used. You can refer to this post https://stackoverflow.com/questions/1041866/what-is-the-effect-of-extern-c-in-c – yxz Jul 14 '23 at 14:19
16

This is useful when you want to have a global variable. You define the global variables in some source file, and declare them extern in a header file so that any file that includes that header file will then see the same global variable.

Marlon
  • 19,924
  • 12
  • 70
  • 101
  • Anyway this does not sound very OOP , I would put them into a singleton class... or a function returning a local static value... – RzR Aug 13 '14 at 15:58