The concepts of scope, duration, and linkage cause a lot of confusion, so we’re going to take an extra lesson to summarize everything. Some of these things we haven’t covered yet, and they’re here just for completeness / reference later.
Scope summary
An identifier’s scope determines where the identifier can be accessed within the source code.
- Variables with block scope / local scope can only be accessed within the block in which they are declared (including nested blocks). This includes:
- Local variables
- Function parameters
- User-defined type definitions (such as enums and classes) declared inside a block
- Variables and functions with global scope / file scope can be accessed anywhere in the file. This includes:
- Global variables
- Functions
- User-defined type definitions (such as enums and classes) declared inside a namespace or in the global scope
Duration summary
A variable’s duration determines when it is created and destroyed.
- Variables with automatic duration are created at the point of definition, and destroyed when the block they are part of is exited. This includes:
- Local variables
- Function parameters
- Variables with static duration are created when the program begins and destroyed when the program ends. This includes:
- Global variables
- Static local variables
- Variables with dynamic duration are created and destroyed by programmer request. This includes:
- Dynamically allocated variables
Linkage summary
An identifier’s linkage determines whether multiple declarations of an identifier refer to the same identifier or not.
- An identifier with no linkage means the identifier only refers to itself. This includes:
- Local variables
- User-defined type definitions (such as enums and classes) declared inside a block
- An identifier with internal linkage can be accessed anywhere within the file it is declared. This includes:
- Static global variables (initialized or uninitialized)
- Static functions
- Const global variables
- Functions declared inside an unnamed namespace
- User-defined type definitions (such as enums and classes) declared inside an unnamed namespace
- An identifier with external linkage can be accessed anywhere within the file it is declared, or other files (via a forward declaration). This includes:
- Functions
- Non-const global variables (initialized or uninitialized)
- Extern const global variables
- Inline const global variables
- User-defined type definitions (such as enums and classes) declared inside a namespace or in the global scope
Identifiers with external linkage will generally cause a duplicate definition linker error if the definitions are compiled into more than one .cpp file (due to violating the one-definition rule). There are some exceptions to this rule (for types, templates, and inline functions and variables) -- we’ll cover these further in future lessons when we talk about those topics.
Also note that functions have external linkage by default. They can be made internal by using the static keyword.
Variable scope, duration, and linkage summary
Because variables have scope, duration, and linkage, let’s summarize in a chart:
Type | Example | Scope | Duration | Linkage | Notes |
---|---|---|---|---|---|
Local variable | int x; | Block | Automatic | None | |
Static local variable | static int s_x; | Block | Static | None | |
Dynamic variable | int *x { new int{} }; | Block | Dynamic | None | |
Function parameter | void foo(int x) | Block | Automatic | None | |
External non-constant global variable | int g_x; | File | Static | External | Initialized or uninitialized |
Internal non-constant global variable | static int g_x; | File | Static | Internal | Initialized or uninitialized |
Internal constant global variable | constexpr int g_x { 1 }; | File | Static | Internal | Must be initialized |
External constant global variable | extern constexpr int g_x { 1 }; | File | Static | External | Must be initialized |
Inline constant global variable | inline constexpr int g_x { 1 }; | File | Static | External | Must be initialized |
Internal constant global variable | const int g_x { 1 }; | File | Static | Internal | Must be initialized |
External constant global variable | extern const int g_x { 1 }; | File | Static | External | Must be initialized at definition |
Inline constant global variable | inline const int g_x { 1 }; | File | Static | External | Must be initialized |
Forward declaration summary
You can use a forward declaration to access a function or variable in another file:
Type | Example | Notes |
---|---|---|
Function forward declaration | void foo(int x); | Prototype only, no function body |
Non-constant global variable forward declaration | extern int g_x; | Must be uninitialized |
Const global variable forward declaration | extern const int g_x; | Must be uninitialized |
Constexpr global variable forward declaration | extern constexpr int g_x; | Not allowed, constexpr cannot be forward declared |
What the heck is a storage class specifier?
When used as part of an identifier declaration, the static
and extern
keywords are called storage class specifiers. In this context, they set the storage duration and linkage of the identifier.
C++ supports 4 active storage class specifiers:
Specifier | Meaning | Note |
---|---|---|
extern | static (or thread_local) storage duration and external linkage | |
static | static (or thread_local) storage duration and internal linkage | |
thread_local | thread storage duration | Introduced in C++11 |
mutable | object allowed to be modified even if containing class is const | |
auto | automatic storage duration | Deprecated in C++11 |
register | automatic storage duration and hint to the compiler to place in a register | Deprecated in C++17 |
The term storage class specifier is typically only used in formal documentation.
![]() |
![]() |
![]() |
"Second, astute readers may note that global types have external linkage, but their definitions don’t cause a linker error when included in multiple files. This is because types, templates, and extern inline functions have an exemption that allows them to be defined in more than one file, so long as the definitions are identical. Otherwise, they wouldn’t be of much use."
I don't get this, can someone explain this using a example please?
class.hpp
learning.cpp
main.cpp
class.hpp was included in multiple files, so `C` and `i` are defined multiple times.
`i` causes an error, because variables can only be defined once.
`C` is fine, because types can be defined in multiple files.
Have there even been any custom types up to this point?
No but now I understand this, thanks a lot!
Lesson 4.2 (Global variables and linkage) states:
„A variable with internal linkage is called an internal variable (or static variable).“
And this lessons states:
„A static duration variable (also called a “static variable”)“
So „static variable“ has actually two different meanings? Very confusing..
Static variable normally refers to static duration, not internal linkage. I've amended lesson 4.2.
Ok, thank you for the clarification and also for creating and maintaining this awesome website!
globals.cpp :
globals.h :
main.cpp :
I'm getting this error:
Error LNK2001 unresolved external symbol "double globals::pi" (?pi@globals@@3NA) learncpp C:\Users\matri\Desktop\learncpp\learncpp\learncpp\main.obj 1
If I make pi non const everything is ok, but I want pi to be constant, what should I do?
@pi in globals.cpp and @pi in globals.h are different. If you want it to be constexpr, you don't need to declare it extern.
"Variables with static duration are created when the program begins and destroyed when the program ends. This includes:
Global variables
Static local variables"
Static local variables are created when their line is executed first time, right? Not when the program begins.
Memory is reserved when the program starts. They are initialized when execution reaches their declaration.
Hi Alex,
I can't figure out why the following statements seem to contradict.
"
#Identifiers with external linkage will cause a duplicate definition linker error if the definitions are compiled into more than one .cpp file.
#Second, astute readers may note that global types have external linkage, but their definitions don’t cause a linker error when included in multiple files. This is because types, templates, and extern inline functions have an exemption that allows them to be defined in more than one file, so long as the definitions are identical. Otherwise, they wouldn’t be of much use "
Please help clarify.
What part seems to contract? Maybe try re-reviewing the one-definition rule in lesson 1.7 and see if that helps clarify.
Are Static duration variables created at the start of program or at the place where they are initialized? I do not understand how they can be created before they are initialized.
For example if you have this program:
shouldn't variable num2 be created only when functionb() is called?
The C++ spec gives a lot of leeway as to when variables are created and initialized, and this is no exception.
Static duration local variables are generally "created" at the start of the program. By created, I mean that memory is set aside for those variables.
Static duration local variables may be initialized before the block containing them is entered, or they may be initialized on first entry.
> shouldn't variable num2 be created only when functionb() is called?
No, memory for num2 is typically reserved at the start of the program, and the initialization can happen upon creation (if the initializer is a constant) or on first call.
Thanks for replying Alex!
I have a followup question. Would initialization happen on creation for any type of constant or only compile time constants?
Initialization could happen on creation for any type of constant if creation were deferred to the point of initialization.
That said, the compiler has a huge amount of leeway in terms of when constants are created and initialized, and different compilers may do different things in different cases. The compiler also has leeway to not create compile-time constants as objects at all, and instead just embed the constant value directly in the code. This isn't something you really need to worry about, as the compiler will just "make it work", though it's certainly an interesting line of inquiry.
Thanks a lot for the reply Alex!
With chapter 8 introducing additional meanings for several things, I decided to come back and review scope, duration, and linkage, etc. and their associated keywords (const, constexpr, static, extern, etc.)
Here's some code I wrote while studying the behavior of various variables/definitions/uses. Maybe someone will find it useful.
Regards,
Matt
example.cpp
main.cpp
Hi Alex! Here's a question: is it good practice to give variables the most limited scope as necessary? For example, take the following snippet:
Would it be better to
a) declare tmp inside the loop (but then tmp gets created each iteration -- is that bad?)
b) declare tmp before the loop and assign tmp in the loop (but then tmp does not go out of score after its no longer needed)
c) create a block around the loop and assign tmp at the top of the block (e.g. put the loop in a function)
Hi David!
Choose option a. Your compiler is smart enough not to create @tmp every loop.
Hi nascardriver! Thank you! Ok so if I do this:
Does the compiler define tmp once and then assign it to 0 each time at the top of the loop? Or do I need a separate assignment statement?
@tmp will be set to 0.0 every cycle
Hi Alex,
I am trying to understand how the standard library writes the implementation for rand() and I have come accross extern in this way:
What is the extern keyword doing here together with a function? Aren't functions supposed to be extern anyway?
Thanks!
(by the way, you do an amazing job of explaining C++! Thanks!)
Hello Guys!
in the chart above, where it states:
External non-const global variable | int g_x; | File scope | Static duration | External linkage | Initialized or uninitialized
Should we use 'extern int g_x;' instead of 'int g_x;' as quoted above? Please help me to clarify that, because I've understood so far that, in order to make a global variable visible to be used in other files, we have to use the word 'extern', am I wrong? Thx
Non-const global variables are extern by default. If you use the extern keyword in this case, the compiler will think you're defining a forward declaration to a global variable that is defined somewhere else, which probably isn't what you want.
Is a global const variable automatically static and a normal global variable extern?
Const global variables have static duration and internal linkage by default.
Non-const global variables have static duration and external linkage by default.
Why would you use a static global variable instead of defining a local variable in the first line of the main function? From my understanding, both would be destroyed at the end of the program and both could be accessed anywhere in the program.
Thanks!
A local variable in the first line of the main function could only be used within main() (although you could pass it to other functions, it couldn't be accessed directly from outside main()).
sir i have one doubt that can you tell me the best site or tutorial by these i can grasp the full knowledge about data structure and algorithms by these i can learn and grasp the knowledge. please send these on my mail please. it's an humble request.
From IBM site (https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_72/rzarg/cplr081.htm#cplr081):
Internal linkage:
Identifiers declared in the unnamed namespace
From your site:
External linkage:
Non-const global variables (initialized or uninitialized)
Where is true?
When they say unnamed namespace, they don't mean the global namespace, they mean something like this:
Thank you, I really like this page. It summarizes everything beginning of chapter 4 up til now perfectly. I think it would really benefits other beginners if you could do one like this for the other previous chapters
Hello Alex,
I really like your precise distinction between scope and linkage. I already tried two other books and one tutorial on that matter -- only one of those books went into detail as much and its explanations were convoluted (though in the end they were the same as in this tutorial, as far as I can tell)...
That said, from a beginners point of view, I would prefer it if only file scope and block scope were used in the tutorial instead of global and local scope, which could be mentioned only once as common alternatives to the former. In my opinion file scope and block scope are more precise and tell the reader exactly what they are supposed to mean, unlike local and (especially) global scope.
I used to mix up global scope with external linkage, but the expression "file scope" did the trick to distinguish between the two. Perhaps I'm not the only one with that problem ;)
Thank you so much for your amazing work here!
I get it. It confused me too, and people tend to use the terms inconsistently in casual conversation. When people talk about "global scope", they usually mean "file scope and external linkage", which makes the identifier accessible globally throughout the program (hence the name).
Hello Alex!
Thanks for teaching me C++!
I'm sorry if this is rather trivial but....there's a grammatical error in the first line of 'Scope summary'.
Its supposed to be 'An identifier' rather than 'A identifier'. Sorry for my bad English - English isn't my first language!
Thanks!
Thanks for pointing that out. Fixed!
When We Use main function in multiple files in a project it produces a linker error,
is it due to the multiple definition of main function ? I am asking because my code::blocks linker produces an error when i try to do so !
Second, astute readers may note that global types have external linkage, but their definitions don’t cause a linker error when included in multiple files. This is because types, templates, and extern inline functions have an exemption that allows them to be defined in more than one file, so long as the definitions are identical. Otherwise, they wouldn’t be of much use.
Explain Me this too using an example !
1) A program is only allowed to have one main() function.
2) Define an enum in a header file, then include that header file into two different .cpp files. Each .cpp file will get a copy of the enum definition, but this will not cause a linker error.
Ok So U Talked about enums in this example too....i thought u only referred to vars.....Thanks
"This is because types, templates, and extern inline functions have an exemption that allows them to be defined in more than one file, so long as the definitions are identical." What is the point of allowing them to be defined them more than once, provided that the definitions are identical? Just so you don't get a linker error and thus avoid crashing the program? It seems like it is best to avoid defining them more than once at all. Is there any cases where it would be useful to define them more than once (with the same definition)?
Maybe also change the example of the static local variable in the table to int s_x?
Looks like the next lesson covers why it is not necessary to use std::cout every time with cout, so long as using std::cout is used in the first instance, or using namespace std is used (although it's best to avoid doing this.
For this conversation, let's be more precise about how we use the term "define".
You should only define your types in one place (most often, in a header file) -- redundant code is bad. However, in any program of sufficient complexity, that header file will be #included into multiple .cpp files. This propagates that type definition into multiple code files, each of which will be independently compiled and linked. Without this exemption, the linker would note that a definition has been defined (actually propagated) in multiple places, and flag an error.
So basically, this exemption allows us to propagate types, templates, and inline function definitions from a single header out to multiple code files, where they can be used.
Also, updated the static local variable per your suggestion. Thanks!
Ah OK, that makes sense. Thanks Alex!
Give the man a knighthood.
Hi Alex,
I don't understand the second row (Static local variable) in the chart.
Example: static int x;
Scope: Block scope
Duration: Static duration
Linkage: No linkage
Note:
I believe "Static Local Variable" is covered in the very last section 4.3.
I think "Static Local Variable" has Static duration if I both define a variable AND give it an initial value in the same step(for example: static int x = 1;).
In the above example, x is not initialized. I am not sure if x has Static or automatic duration? If x has static duration then why the output of the following code is different from another?
#include <iostream>
void incrementAndPrint()
{
using namespace std;
static int s_value = 0; // static duration variable initialized
++s_value;
cout << s_value << endl;
}
int main()
{
incrementAndPrint();
incrementAndPrint();
incrementAndPrint();
return 0;
}
Which outputs:
1
2
3
Declaring a static duration variable, then assigning a literal to it:
#include <iostream>
void incrementAndPrint()
{
using namespace std;
static int s_value; // static duration variable declared
s_value = 0; // static duration variable assigned
++s_value;
cout << s_value << endl;
}
int main()
{
incrementAndPrint();
incrementAndPrint();
incrementAndPrint();
return 0;
}
Which outputs:
1
1
1
Static variables have static duration regardless of whether you initialize them or not. In your example, you're not initializing the static (which would only happen once, when the static is created). Instead, you're assigning a value to the static variable, which happens every time the function runs. So even though your static s_value is keeping its value between function calls, you're resetting it back to 0 via assignment every function call.
This is why we typically initialize static variables, not assign values to them.
Indianapolis IN a quic k eep https://edmondscommerce.github.io/index.smp #945482899063326634NAW Walterjacobs89@gmail.com@gmail.com password 1431st
" (initialized or uninitialized) "
Why do you use this prenthesis
Just to be explicit that this covers both cases.
Ok
Can you please explain how "Extern const global variable" has external linkage ? can we access any variable defined as const in other file without using namespace?
a.cxx:
extern const int a(5);
b.cxx:
extern const int a;
int main(){
std::cout << a << std::endl;
}
It gives an error as "b.cxx:(.text+0x6): undefined reference to `a' "
Worked fine for me on Visual Studio 2015. Are you sure both a.cxx and b.cxx got compiled and linked properly?
In section "Duration summary", the listings for automatic duration and static duration (local variables) should be updated to reflect that the variables are created during definition, not when the block is entered.
Updated. Thanks for pointing that out.
This is very helpful. Thank you
Thanks Alex,
I need to clear one more thing, Consider I have 2 Task and I called a common function from both the task which having a static local variable , So from one task I am accessing and set one value to that static variable, and through another task I read that value. So In both case am accessing the same local static variable. My doubt is ,am accessing the same memory ? able to consider that variable as a shared variable or shared memory?
In both cases, you're accessing the same local static variable, which uses the same memory. It's not really shared memory -- it's just a variable that you can access whenever you're inside the function (doesn't matter which function it was called from).
Hi Alex
Why it's not shared memory? As per my knowledge shared memory is the memory in which a common memory get accessed from 2 different task, is it correct ? Would you please give me the definition of Shared memory?
Maybe I'm misunderstanding what you mean by task. If by task you mean "process" or "thread" (or anything else that can run in parallel), then yes, the memory would be shared.
Yes, I meant Task as two separate Process that may or may not be run parallel.
Now everything is clear
Thanks Alex.
The effort you put in this site is really worth for learner
Hi Alex,
Thanks a lot for the replay
I tried indirectly, Like address of a static local variable assigned to a global pointer and deferred at another function. Compiler not showing any error and I am getting the expected result as well. As per my knowledge the lime time of the static local variable till up to the end of the program , is it correct? then why can't access the local static variable outside that function(indirectly)? is any risk involved in this way like data overwriting?
Yes, the lifetime of a local static variable is until the end of the program. But the scope of a local static variable is still only within the function in which it is declared, the same as a local non-static variable. The scope governs where you can access the variable, which is why you can't use it directly outside the function.
You can access the variable outside the function indirectly (via a pointer or reference), but even though you can do this, it's not advised.
Hi, I have one doubt.
is it possible to access a static local variable in a function from the main function. if it possible to access, then that data is safe or not?
No, it is not possible (at least not directly). Static local variables are only visible within the function in which they are declared.
Wow. I was literally just about to write some kind of summary like this to supplement notes I've taken from your website. Thanks! I've been using this site for years: Perhaps the best non-book resource that there is on C++.
Got cleared all of my former doubts...Bro Thankyou so much for this awsome site...