In the last lesson, you learned that variables declared inside a function are called local variables. Local variables have block scope (they are only visible within the block they are declared), and have automatic duration (they are created at the point of definition and destroyed when the block is exited).
Variables declared outside of a function are called global variables. Global variables have static duration, which means they are created when the program starts and are destroyed when it ends. Global variables have file scope (also informally called “global scope” or “global namespace scope”), which means they are visible until the end of the file in which they are declared.
Defining global variables
By convention, global variables are declared at the top of a file, below the includes, but above any code. Here’s an example of a couple of global variables being defined.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#include <iostream> // Variables declared outside of a function are global variables int g_x; // global variable g_x const int g_y(2); // global variable g_y void doSomething() { // global variables can be seen and used everywhere in program g_x = 3; std::cout << g_y << "\n"; } int main() { doSomething(); // global variables can be seen and used everywhere in program g_x = 5; std::cout << g_y << "\n"; return 0; } |
Similar to how variables in an inner block with the same name as a variable in an outer block hides the variable in the outer block, local variables with the same name as a global variable hide the global variable inside the block that the local variable is declared in. However, the global scope operator (::) can be used to tell the compiler you mean the global version instead of the local version.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include <iostream> int value(5); // global variable int main() { int value = 7; // hides the global variable value ++value; // increments local value, not global value --(::value); // decrements global value, not local value (parenthesis added for readability) std::cout << "local value: " << value << "\n"; std::cout << "global value: " << ::value << "\n"; return 0; } // local value is destroyed |
This code prints:
local value: 8 global value: 4
However, having local variables with the same name as global variables is usually a recipe for trouble, and should be avoided whenever possible. By convention, many developers prefix global variable names with “g_” to indicate that they are global. This both helps identify global variables as well as avoids naming conflicts with local variables.
Internal and external linkage via the static and extern keywords
In addition to scope and duration, variables have a third property: linkage. A variable’s linkage determines whether multiple instances of an identifier refer to the same variable or not.
A variable with no linkage can only be referred to from the limited scope it exists in. Normal local variables are an example of variables with no linkage. Two local variables with the same name but defined in different functions have no linkage -- each will be considered an independent variable.
A variable with internal linkage is called an internal variable (or static variable). Variables with internal linkage can be used anywhere within the file they are defined in, but can not be referenced outside the file they exist in.
A variable with external linkage is called an external variable. Variables with external linkage can be used both in the file they are defined in, as well as in other files.
If we want to make a global variable internal (able to be used only within a single file), we can use the static keyword to do so:
1 2 3 4 5 6 |
static int g_x; // g_x is static, and can only be used within this file int main() { return 0; } |
Similarly, if we want to make a global variable external (able to be used anywhere in our program), we can use the extern keyword to do so:
1 2 3 4 5 6 7 8 9 |
extern double g_y(9.8); // g_y is external, and can be used by other files // Note: those other files will need to use a forward declaration to access this external variable // We'll discuss this in the next section int main() { return 0; } |
By default, non-const variables declared outside of a function are assumed to be external. However, const variables declared outside of a function are assumed to be internal.
Variable forward declarations via the extern keyword
In the section on programs with multiple files, you learned that in order to use a function declared in another file, you have to use a function forward declaration.
Similarly, in order to use an external global variable that has been declared in another file, you must use a variable forward declaration. For variables, creating a forward declaration is done via the extern keyword (with no initialization value).
Note that this means the “extern” keyword has different meanings in different contexts. In some contexts, extern means “give this variable external linkage”. In other contexts, extern means “this is a forward declaration for an external variable that is defined somewhere else”. We’ll summarize these usages in lesson 4.3a -- Scope, duration, and linkage summary.
Here is an example of using a variable forward declaration:
global.cpp:
1 2 3 4 5 6 |
// define two global variables // non-const globals have external linkage by default int g_x; // external linkage by default extern int g_y(2); // external linkage by default, so this extern is redundant and ignored // in this file, g_x and g_y can be used anywhere beyond this point |
main.cpp:
1 2 3 4 5 6 7 8 9 10 11 |
extern int g_x; // forward declaration for g_x (defined in global.cpp) -- g_x can now be used beyond this point in this file int main() { extern int g_y; // forward declaration for g_y (defined in global.cpp) -- g_y can be used beyond this point in main() only g_x = 5; std::cout << g_y; // should print 2 return 0; } |
If the variable forward declaration is declared outside of a function, it applies for the whole file. If the variable forward declaration is declared inside a function, it applies within that block only.
If a variable is declared as static, trying to use a forward declaration to access it will not work:
constants.cpp:
1 |
static const double g_gravity(9.8); |
main.cpp:
1 2 3 4 5 6 7 8 9 |
#include <iostream> extern const double g_gravity; // This will satisfy the compiler that g_gravity exists int main() { std:: cout << g_gravity; // This will cause a linker error because the only definition of g_gravity is inaccessible from here return 0; } |
Note that if you want to define an uninitialized non-const global variable, do not use the extern keyword, otherwise C++ will think you’re trying to make a forward declaration for the variable.
Function linkage
Functions have the same linkage property that variables do. Functions always default to external linkage, but can be set to internal linkage via the static keyword:
1 2 3 4 5 6 |
// This function is declared as static, and can now be used only within this file // Attempts to access it via a function prototype will fail static int add(int x, int y) { return x + y; } |
Function forward declarations don’t need the extern keyword. The compiler is able to tell whether you’re defining a function or a function prototype by whether you supply a function body or not.
The one-definition rule and non-external linkage
In lesson 2.7 -- Forward declarations and definitions, we noted that the one-definition rule says that an object or function can’t have more than one definition, either within a file or a program.
However, it’s worth noting that non-extern objects and functions in different files are considered to be different entities, even if their names and types are identical. This makes sense, since they can’t be seen outside of their respective files anyway.
File scope vs. global scope
The terms “file scope” and “global scope” tend to cause confusion, and this is partly due to the way they are informally used. Technically, in C++, all global variables in C++ have “file scope”. However, informally, the term “file scope” is more often applied to file scope variables with internal linkage only, and “global scope” to file scope variables with external linkage.
Consider the following program:
global.cpp:
1 |
int g_x(2); // external linkage by default |
main.cpp:
1 2 3 4 5 6 7 8 |
extern int g_x; // forward declaration for g_x -- g_x can be used beyond this point in this file int main() { std::cout << g_x; // should print 2 return 0; } |
g_x has file scope within global.cpp -- it can not be directly seen outside of global.cpp. Note that even though it’s used in main.cpp, main.cpp isn’t seeing g_x, it’s seeing the forward declaration of g_x (which also has file scope). The linker is responsible for linking up the definition of g_x in global.cpp with the use of g_x in main.cpp.
Global symbolic constants
In section 2.9 -- Symbolic constants and the const keyword, we introduced the concept of symbolic constants, and defined them like this:
constants.h:
1 2 3 4 5 6 7 8 9 10 11 12 |
#ifndef CONSTANTS_H #define CONSTANTS_H // define your own namespace to hold constants namespace Constants { const double pi(3.14159); const double avogadro(6.0221413e23); const double my_gravity(9.2); // m/s^2 -- gravity is light on this planet // ... other related constants } #endif |
While this is simple (and fine for smaller programs), every time constants.h gets #included into a different code file, each of these variables is copied into the including code file. Therefore, if constants.h gets included into 20 different code files, each of these variables is duplicated 20 times. Header guards won’t stop this from happening, as they only prevent a header from being included more than once into a single including file, not from being included one time into multiple different code files. This duplication of variables isn’t really that much of a problem (since constants aren’t likely to be huge), but changing a single constant value would require recompiling every file that includes the constants header, which can lead to lengthy rebuild times for larger projects.
We can avoid this problem by turning these constants into const global variables, and changing the header file to hold only the variable forward declarations:
constants.cpp:
1 2 3 4 5 6 7 |
namespace Constants { // actual global variables extern const double pi(3.14159); extern const double avogadro(6.0221413e23); extern const double my_gravity(9.2); // m/s^2 -- gravity is light on this planet } |
constants.h:
1 2 3 4 5 6 7 8 9 10 11 12 |
#ifndef CONSTANTS_H #define CONSTANTS_H namespace Constants { // forward declarations only extern const double pi; extern const double avogadro; extern const double my_gravity; } #endif |
Use in the code file stays the same:
1 2 |
#include "constants.h" double circumference = 2 * radius * Constants::pi; |
Because global symbolic constants should be namespaced (to avoid naming conflicts with other identifiers in the global namespace) and are read-only, the use of the g_ prefix is not necessary.
Now the symbolic constants will get instantiated only once (in constants.cpp), instead of once every time constants.h is #included, and the other uses will simply refer to the version in constants.cpp. Any changes made to constants.cpp will require recompiling only constants.cpp.
However, there are a couple of downsides to doing this. First, these constants are now considered compile-time constants only within the file they are actually defined in (constants.cpp), not anywhere else they are used. This means that outside of constants.cpp, they can’t be used anywhere that requires a compile-time constant (such as for the length of a fixed array, something we talk about in chapter 6). Second, the compiler may not be able to optimize these as much.
Given the above downsides, we recommend defining your constants in the header file. If you find that for some reason those constants are causing trouble, you can move them into a .cpp file as per the above as needed.
A word of caution about (non-const) global variables
New programmers are often tempted to use lots of global variables, because they are easy to work with, especially when many functions are involved. However, use of non-const global variables should generally be avoided altogether! We’ll discuss why in the next section.
Summary
Global variables have global scope, and can be used anywhere in the program. Like functions, you must use a forward declaration (via keyword extern) to use a global variable defined in another file.
By default, non-const global variables have external linkage. You can use the static keyword to explicitly make them internal if desired.
By default, const global variables have internal linkage. You can use the extern keyword to explicitly make them external if desired.
Use a g_ prefix to help identify your non-const global variables.
Here’s a summary chart of the use of the extern and static keywords for non-const and const variable use cases:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// Uninitialized definition: int g_x; // defines uninitialized global variable (external linkage) static int g_x; // defines uninitialized static variable (internal linkage) const int g_x; // not allowed: const variables must be initialized // Forward declaration via extern keyword: extern int g_z; // forward declaration for global variable defined elsewhere extern const int g_z; // forward declaration for const global variable defined elsewhere // Initialized definition: int g_y(1); // defines initialized global variable (external linkage) static int g_y(1); // defines initialized static variable (internal linkage) const int g_y(1); // defines initialized const variable (internal linkage) // Initialized definition w/extern keyword: extern int g_w(1); // defines initialized global variable (external linkage, extern keyword is redundant in this case) extern const int g_w(1); // defines initialized const global variable (external linkage) |
Quiz
1) What’s the difference between a variable’s scope, duration, and linkage? What kind of scope, duration, and linkage do global variables have?
Quiz Solutions
![]() |
![]() |
![]() |
For whatever reason, the /n command won’t work. Could you give me some possible solutions?
It's \n
Not /n
Wow, I should’ve figured lol. Thanks!
@Alex, in your example about how the global scope resolution operator can be used to specify that the global variable should be used, you used postfix operators. It is not necessary to use the postfix operators. It also breaks a rule given in a previous tutorial (3.3 Increment/decrement operators, and side effects).
Thanks, updated!
Now that I see
I think parenthesizing it like this could make it more readable:
That is not a big problem, however, merely a suggestion / personal preference.
Good suggestion. I've updated the lesson. Thanks!
main.cpp
global_g.cpp
Compiler error :
Undefined reference to 'global_g'.
Please help
@global_g is never defined. "extern" means that the variable exists somewhere and it's safe to use it. Your code doesn't contain this "somewhere". You say twice that @global_g exists, but you never create it.
Remove the "extern" is @global_g.cpp.
Your compiler will see @global_g in @main.cpp, search for it, and find it in @global_g.cpp.
Ok i got it thanks for the reply.
It works when i use
Because the compiler knows that this is a declaration with external linkage and not forward declaration.
But as i have used
in both the files it treats both as forward declaration as it is not smart enough to automatically decide in which file i have declared global_g.
Hi Alex | nas | fellow learners!
When I was viewing cpp on wikipedia it was said that "C" code can be written in CPP with the (extern "C") keyword and there is no mention of it here. So is there any information regarding this.
Rather than answering this, I'll give you this link: https://stackoverflow.com/questions/1041866/what-is-the-effect-of-extern-c-in-c
Which does a much better job than I could of answering this question.
All clear, muchas gracias
is it fair to say that:
If you need external linkage to multiple files for compile time constants, then initialize the "extern const" in header file
otherwise, initialize the "extern const" in cpp file and forward declare it in header file
if this is a valid point, then I think it would be good to add this into summary
I recommend defining global constants in a header file (rather than a source file) unless you find some specific reason not to (e.g. you keep changing the values and it's causing your entire huge program to recompile).
Follow up question on this Alex, in 4.3a section, you say this:
Identifiers with external linkage will cause a duplicate definition linker error if the definitions are compiled into more than one .cpp file.
would the above statement be one more reason (apart from this reason : you keep changing the values and it's causing your entire huge program to recompile) for defining global variables in their own cpp files, forward declaring these global variables in a header file and then including them in 2 cpp files.
For example:
file1 :
globalConst.cpp
file2:
file3: 1.cpp
file4: 2.cpp
No. Const global variables defined in the header should be defined with internal linkage (they have this by default) so you can #include them into any file that needs them without running into linker errors. Because they have internal linkage, the compiler and linker will treat each as independent, and no conflict will result.
In the summary:
The third comment should refer to const, not variable, shouldn't it?
Indeed. Thanks for pointing out the copy/paste error.
When I try to assign g_x a value in the global scope why does it give me an error?
Because you can't have code outside of functions. If you want to initialize @g_x, you need to do so at it's definition.
Hi, if constants.h has
#ifndef CONSTANTS_H
#define CONSTANTS_H
const double pi(3.14159);
const double avogadro(6.0221413e23);
const double my_gravity(9.2); // m/s^2 -- gravity is light on this planet
// ... other related constants
#endif
and constants.h is subsequently included by 20 over code files and each of these variables is duplicated 20 times. Would this a problem for linker as this violates One Definition rule?
Hi limcheling!
> Would this a problem for linker as this violates One Definition rule?
Constants don't fall under the one-definition-rule. If one of the variables was non-const, linking would fail.
In the above example for 'Global Symbolic Constants' why does both constants.h and constants.cpp use the namespace 'Constants'? I removed the namespace in the header and adjusted the reference but it called a linker error, presumably because the forward declarations didn't describe the namespace used in the initialization? I then tried removing the namespace from the constants.cpp and keeping the namespace in the header file and reference but it again provided the same linker error.
The compiler needs to know that the forward declarations in the header are inside the namespace so it can enforce the proper syntax, and the linker needs to know that the definitions inside the code file are also inside the namespace so it can link everything up properly.
Thank a lot Alex. Your C++ tutorials are great.
I have a question about the default use of constant variables. They have by default static scope.
The next code will not compile and i understand why :
But why when i add a forward declaration for the const global variable in the constantes.cpp file using the keyword "extern", the program compile.
The g_gravity variable still have a file (static) scope
It looks like your declaration of g_gravity as extern is telling the compiler to modify g_gravity so that it has external linkage.
I've never seen anybody do this in practice, and it seems like bad form to use it in this manner.
Generally, we have this situation when we use a header file to define the variable forward declarations. Then we include this header file in the main.cpp file and the other cpp file (constantes.cpp)
Thanks,
Hello guys!
thank you so much for such a good materials and forum!
My question is: once I have a .cpp file, let's say the same above:
And the .h file, which is same above in the tutorial:
Should I have to put "#include "constants.h" in the .cpp file? Will the compiler recognize a declaration/definition just by using the "same name"(constants) for these two files?
Thanks
Never mind!
I tried to run a new program with them and it's fine. I thought I should include the name of the header file in its respective .cpp file. Thanks.
Hey Alex.
I've been following and learning cpp here for a month now,and so far hopefully i am on good way.
Thing is,i still dont know or better like i am not sure how to write programs shown in examples.
I dont know exactly what to input where and when,so is it normal? Is it normal for a beginner to "not know" how to write a program in so far lectures?
As well i am worried that after finishing this whole index i wont be able to write a bit more complexed programs. Should i worry about it?
After finishing this index i will swap to udemy. For more courses.
But yeah,is it normal that i dont know how to write programs properly and without looking at solutions from quiz and examples?
I really do understand lectures,each one of these,structure and way of writing programs is still not clear.
If you're generally able to at least follow the lessons and understand the examples (both syntax and structure), then you probably just need more practice in creating things on your own.
If you're struggling to understand the structure then you may need to spend more time reading about functions and modularity. It's an important concept to get now so your programs aren't a mess later.
Hi Alex, Great Tutorials!
ext1.cpp
ext.cpp
Now to use the x which is by default extern in ext1, I realized we cannot link them togerther(g++ ext.cpp ext1.cpp) since both have in main(), So the int x(declared in ext1) would be useless if we have main function in the program, so my doubt was to use such x do we always have to define it in a file which has no main or other functions and just the forward declarations of the global variables?
Hi Saumitra!
"a file which has no main or other functions and just the forward declarations of the global variables?"
It can contain other functions, but there may only be one main function.
Thanks for the reply nascardriver!
Here by other functions(if the 2 files have same function names)i meant that it is causing multiple definitions conflict when i compile them together(g++ ext.cpp ext1.cpp) ,Even if i include just main it will cause multiple definition conflict.
You can't have two functions with the same signature (return type, name, parameters) in the same scope. You can however have functions that have not yet been declared in the file file the extern variable.
So bottom line, we cant use a extern variable if the file in which it has been defined has same function names(including int main()) as the file in which it is forward declared for usage.
This has nothing to do with the extern variable. Take the following setup for example
This won't compile, because @hello has been defined more than once.
Yea you are right that it wont compile,I just wanted to point out that
as Alex said here that g_y in this snippet has external linkage and it can be used by other files but technically we cant because it contains (int main()) and as we try to compile it with the file in which we want to use it, it would just wont work due to multiple declarations of(int main()) so even though it has external linkage ,we wont be able to use it.
Not true. It can be used by other files in the same project (those files shouldn't have their own main() functions, because a program can only have 1 main function).
So something like this:
main.cpp
foo.cpp
In the example of static const double g_gravity in constants.cpp, your comment in main.cpp says that the attempt to access g_gravity would cause a compiler error. However I believe that this cannot be, as the compiler ignores the contents of constants.cpp when compiling main.cpp and thus will not know of the static keyword, and you will actually get a linker error instead. g_gravity is declared in main.cpp which is enough for the compiler. However the definition of g_gravity in constants.cpp is hidden from the linker by the static keyword and it will not find any other definition and thus fail.
Quite right. Comments updated as appropriate. Thanks for pointing out the error.
One thing to note about linking object files is that g++(C++14) can't catch this. main() will reassign the const and crash. It doesn't realize that your forward declaration in main.cpp doesn't match the identifier in globals.cpp.
globals.cpp
main.cpp
I didn't know that! Interesting. Thanks for teaching me something.
Because global symbolic constants should be namespaced . why ?
Hi Hamed!
A quick example of why having global constants/variables/functions not in a namespace is bad.
There's a function "min" in the <algorithm> header. This function is in the "std" namespace. There's also another function (actually a macro) in some windows header which is also called "min". Both of these functions return the smaller of two numbers.
For simplicity, we'll assume the "std::min" function wasn't in a namespace or we're "using namespace std;".
Look at the following code
Which function is supposed to be called here? The std::min function or the windows min function?
I don't know if the compiler would prefer one over the other, but this is definitely problematic.
This can be avoided by having global constants/variables/functions in a namespace and not "using namespace x;".
To help avoid naming conflicts with other things in the global namespace. I've added this bit of context to the lesson.
Hi Alex!
I'm trying to understand the concept of extern and static but the code gives me strange error first defined here .. why ?
main.cpp
constants.h
global.cpp
Hi Hamed O.Khaled!
The code you posted compiles and runs without problems for me, please post the complete file content and error messages.
Without knowing what exactly is happening I can only suggest you to not declare variables or constants in header files, this can lead to "first defined here" errors. Instead, have a forward declaration (by using "extern") in the header and have the actual declaration in the corresponding source file. I'm talking about your "pi" constant.
What error are you getting? I don't see anything wrong here, and it seems to compile fine on Visual Studio 2017.
Hi Alex. At the top, you say "variables declared outside of a block are called global variables." However, in the section about symbolic constants, you define global variables in a namespace:
(constants.cpp)
Why are namespace blocks different from other blocks?
Great question -- the short answer is that my definition is clearly inadequate. I've updated my definition thusly:
A local variable is one defined inside a function (not inside a block).
A global variable is one defined outside a function (not outside a block).
Under this definition, variables declared outside a function but inside a namespace block are global variables as they should be.
Thanks for pointing out the inconsistency!
I really appreciate your C++ tutorials, but I am a bit confused at the part "Global symbolic constants" when you say "Given the above downsides, we recommend defining your constants in the header file." Earlier on you say that this method is good for smaller programs, at least that's the method I think you're referring to. If not, could you provide an example of what it should look like? Also, in this method should I use extern when initializing the variables in the namespace?
Thanks -Jeffery
Yes, that's the method I'm referring to. You should only use extern if you're defining a global const that you want to have external access to (e.g. from some other file).
There's a summary of scope, duration, and linkage in lesson 4.3a.
This is the most confusing section so far! ;+P Final (I hope) confusion concerns "static". In your 'chart', you say:
"// Initialized definition:
...
const int g_y(1); // defines initialized static variable (internal linkage)"
Why is this constant variable (confusing enough!) labeled as "static"?
Never mind. I didn't read the rest of the comments and you answered my question with "Global const variable are static by default". I just missed that in the text... several times. :wallbash:
Thanks for your great teaching gift to us!
Yes, it's super confusing. The good news is that you won't be declaring global variables very often (and if you do, they'll most likely be const values in a header somewhere).
Hi Alex,
I made a test and defined a global variable below a function definition instead of putting it at the top of the file:
The compiler says that g_test is an undeclared identifier.
Does this mean that global variable's scope is not exactly all of the file? Rather, it starts from the point of definition till the end of the file?
Is that also why you should put its definition at the very top of the file?
Thank you!
Yes, even though the variable is global in nature, the parts of the file above where the variable is defined can't see the variable (unless you've forward declared it).
Hi Alex, excellent tutorials you made.
so what should be put in constants.cpp , forward declarations or the actual constants and what should we do in case we need a compile-time constant.
constants.cpp should contain the actual constant definitions.
If you need a compile time constant, put the constant definition in the header file. I recommend using the header method (at least to start) anyway.
Two questions: what exactly is covered by the namespace? i'm trying to parse together what the usages of namespace ought to be.
and i have a confusion i can't quite resolve. when you say "However, there is a downside to doing this: these constants are no longer considered compile-time constants, and thus can’t be used anywhere that requires a compile-time constant."
So what exactly would be a formidable example of compile-time constants? and how exactly does that relate to the example/method shown of symbolic constants and headers? and also how does that differ from non-compile time constants? not quite connecting the dots there and any compare and contrast will help very greatly.
Just wanna say thank you as well! I was terribly skeptical about an all text/reading tutorial, but jeez this is way better than most video tutorials! Thank you for your service! srsly.
I'm not sure I understand your first question. Anything can be put inside a namespace. Namespaces are just containers to help prevent naming collisions.
A formidable example of a compile-time constant would be as the length of a fixed array (which we cover in chapter 6):
Non-compile time constants would be like a const function parameter. It's treated as const within the function, but the value isn't known until runtime:
Thank you kindly! I think I am starting to understand the difference between compile time vs runtime.
In the example under symbolic constants section with the adjusted header method, why exactly would these values not be resolved at compile-time? I can see the clear difference in how the values are handled between declaring the const values directly in the header, vs. simply calling the values directly in .cpp files instead. But why does this difference mean that the const values are resolved at runtime?
Hopefully i've worded this well enough. :p
I realized I made a minor mistake: the const values in the .cpp file ARE considered compile time constants within the file in which they are defined (constants.cpp). This is because the compiler can see the actual definition for those constants.
However, everywhere else, the compiler only sees the forward declaration, and it's up to the linker to connect the identifier with the actual definition in another file. That happens post-compile, so the compiler can't treat it as a compile time constant.
AH okay that makes MUCH more sense. so the trade off for that method would just be that you would have to keep track of the values you are running through those variables i suppose?
> so the trade off for that method would just be that you would have to keep track of the values you are running through those variables i suppose?
I wouldn't consider that a trade-off. Half the point of using symbolic constants is so you don't have to remember specific values, just the name of the thing you want.
what is the duration of global variables having external linkage?
Static duration. Linkage doesn't affect duration.
Alex,
"Variables declares outside of a block are called global variables". There are many blocks, so outside of which block? Should we say a variable, which is accessible in any block of a file, is global.
Accessible, visible or to be used - means the same - accessible?
About linkage … Basically linkage either extends (extern) or constrain (static) the scope.
1. The most intuitive understanding of global scope is the example of defining constants via namespace Constants in .cpp and .h files. No forward declaration or any additional words are required, except ‘Constants::’.
2. Extern - is a master key to unlock access to a variable, declared in other file.
3. Static - is master key to block access to a variable from other files.
4. The most intuitive understanding local variable is block variable, declared and defined inside of { }.
A global variable is a variable that is declared outside of _all_ blocks. A variable declared in any block is a local variable. Both global and local variables follow normal scoping rules, where they can be seen by everything after the point of declaration, to the point where they go out of scope (which for local variables is the end of the block in which they are declared, and for global variables is the end of the file).
I have a summary of all of this stuff in a couple of lessons.
these constants are no longer considered compile-time constants, and thus can’t be used anywhere that requires a compile-time constant.
Why did u say this when forward declaration of constants was done in header files instead of their initialization.........??
U said that in this :-
constants.cpp
constants.h:
Use in the code file stays the same:
When the top case is included in other files, the compiler can see the initialization values, so it can treat those as compile time constants. In the bottom case, only the forward declarations are included, and the linker must link those declarations up to the actual variables. Since the linker happens after the compiler, the compiler doesn't have access to the initialization values (except in the specific .cpp file where they are defined) and thus they generally can't be used as compile time constants.
Hi great Teacher(Alex)!
I have a question about static keyword, What means it? where to used it and does its value change time to time or will remain same in the whole program...? please explain static keyword...? what here it means 'static int 6;' ,ok here it's int value of 6 but what the purpose of here static...?? i have a lot of confusion regarding this...
Thanks in advance.
Please read http://www.learncpp.com/cpp-tutorial/43-static-duration-variables/
ok,i got it,Thank you Teacher,All clarifications cleared.
Further clarification of static globals: 'file scope' scope of the whole 'translation unit' and a translation unit includes all other files added with #include directive, not just the one single file where the static global is written in.
Hello. First, I want to thank you for your C++ tutorial, I really think it is the best textbook for C++, most comprehensible and concise. And I understand, that it is hard to find a balance between this two. So, I want to write about my own experience with this article, and try to figure out why it was so hard for me (and may be some other people from comments section) to understand it. May be it helps to make some fixes, that is not so obvious.
I've read the article and comments several times, but still was deeply confused about "extern" keyword. After a couple hours of reading and thinking, I suppose I understood it, but I'm not 100% sure. So, correct me if I'm wrong.
So, extern keyword has 2 meanings:
1) to make a variable external (visible in other files)
1a) but it's already external by default for normal (non-const) variables, so you don't have to use this keyword in that case
1b) and you CANNOT use this keyword for undefined variables, because compiler/linker will think you're using the second meaning of extern keyword.
2) forward declaration for variable, that was declared in some other file
2a) and you HAVE TO use this keyword in order to access variable from another file
2b) it doesn't matter if it's const or not
Now, after (I hope) I understood this, I re-reading this article and I suprisingly see, that aricle was absolutely correct, and everything I had so much trouble with, was already there. So, I'll try to de-cypher why I had hard times understanding it. Some of this points may be obvous for everybody, but me, but I'll try to write as much details as possible.
1) In section "Internal and external linkage via the static and extern keywords" we learn, that to make variable external (visible in other files) we should declare it with keyword extern (and it's default for non-const). But at this point of reading, we have no clue, that it is _necessary_ to use keyword "extern" second time - in other file, in which we want to use it. Yes, now I see the sentence about that in next section, but I can swear I didn't see it while I was re-reading this article several times. I think the reason is - after I read this section ("Internal and external linkage..."), I somehow assumed, that this is enough to make a variable visible in other files, so when I read next section ("Variable forward declarations via the extern keyword") I assumed it describes some other completely separate case (for example, if we didn't declared variable with extern keyword in other file). I think this is the main reason of my misunderstanding, and while article is textually correct, I think absence of some linkage (no pun intended) between this sections make it really hard to grasp.
2) "Similarly, in order to use an external global variable that has been declared in another file, you have to use a variable forward declaration. For variables, creating a forward declaration is also done via the extern keyword (with no initialization value)." - here it is, sentence I didn't see that "you HAVE TO use a variable forward declaration". And I had some trouble with the word "also" from second sentence. For some reason (I think because it is too far away from its context) I thought "also" means "it can be done with or without extern keyword". Now I understand it means "as in previous case, from previous section", but I got it only after already started to write my first version of this long comment, describing my troubles in understanding different sentences. Only after that "clicked" in my head - I completely understood the whole thing.
3) "Note that if you want to define an uninitialized non-const global variable, do not use the extern keyword, otherwise C++ will think you’re trying to make a forward declaration for the variable." - that is not so important, but still. Yes, it was probably my fault, that I didn't see an emphasis on the word "uninitialized". I only understood this sentence after I read an answer about this in comments. But now you can imagine how confusing it was for me when I read it the first time, after all confustions I already got before that =)
So, I think that's the main points. I hope it can help improving this article for the next readers. Thank you for your time, spent in reading my too-long comment and thank you again for your job making this great tutorial available for people around the world =)
Thanks for the great feedback. I've made some tweaks accordingly to help tie the sections together, and make it clearer that extern has different meanings in different contexts.
Thank you.
Hi Alex,
.
.
.
Similarly, if we want to make a global variable external (able to be used anywhere in our program), we can use the extern keyword to do so:
extern double g_y(9.8); // g_y is external, and can be used by other files
int main()
{
return 0;
}
.
.
.
.
Here is an example of using a variable forward declaration:
global.cpp:
// define two global variables
int g_x;
int g_y(2);
// in this file, g_x and g_y can be used anywhere beyond this point
main.cpp:
extern int g_x; // forward declaration for g_x -- g_x can be used beyond this point in this file
int main()
{
extern int g_y; // forward declaration for g_y -- g_y can be used beyond this point in main()
g_x = 5;
std::cout << g_y; // should print 2
return 0;
}
I am wondering why you did not use extern keyword in global.cpp?
Thanks, Have a great day.
Non-const global variables are extern by default. I'll update the lesson with a comment to indicate such.