Usually, you will see the static keyword in these places:
- A static variable inside a function keeps its value between invocations.
- A static global variable or function is "seen" only in the file in which it's declared.
(1) is the more foreign topic if you're a newbie, so here's an example:
#include <stdio.h>
void foo()
{
int a = 10;
static int sa = 10;
a += 5;
sa += 5;
printf("a = %d, sa = %d\n", a, sa);
}
int main()
{
int i;
for (i = 0; i < 10; ++i)
foo();
}
This prints:
a = 15, sa = 15
a = 15, sa = 20
a = 15, sa = 25
a = 15, sa = 30
a = 15, sa = 35
a = 15, sa = 40
a = 15, sa = 45
a = 15, sa = 50
a = 15, sa = 55
a = 15, sa = 60
This is useful for cases where a function needs to keep some state between invocations, and you don't want to use global variables. Beware, however, this feature should be used very sparingly - it makes your code not thread-safe and harder to understand.
(2) is used widely as an "access control" feature. If you have a .c file implementing some functionality, it usually exposes only a few "public" functions to users. The rest of its functions should be made static, so that the user won't be able to access them. This is encapsulation, a good practice.
Quoting Wikipedia:
In the C programming language,
staticis used with global variables and functions to set their scope to the containing file. In local variables,staticis used to store the variable in the statically allocated memory instead of the automatically allocated memory. While the language does not dictate the implementation of either type of memory, statically allocated memory is typically reserved in data segment of the program at compile time, while the automatically allocated memory is normally implemented as a transient call stack.
See here and here for more details.
And to answer your second question, it's not like in C#.
In C++, however, static is also used to define class attributes (shared between all objects of the same class) and methods. In C there are no classes, so this feature is irrelevant.
Additionally, in C, static can be used in array declarators to specify minimum size of the array (non-function array declarators cannot use this keyword). Consider this declaration:
void func(int foo[static 42]);
The function func() takes an array of at least 42 elements.
Note that C++ does not support this use of the static keyword.
Usually, you will see the static keyword in these places:
- A static variable inside a function keeps its value between invocations.
- A static global variable or function is "seen" only in the file in which it's declared.
(1) is the more foreign topic if you're a newbie, so here's an example:
#include <stdio.h>
void foo()
{
int a = 10;
static int sa = 10;
a += 5;
sa += 5;
printf("a = %d, sa = %d\n", a, sa);
}
int main()
{
int i;
for (i = 0; i < 10; ++i)
foo();
}
This prints:
a = 15, sa = 15
a = 15, sa = 20
a = 15, sa = 25
a = 15, sa = 30
a = 15, sa = 35
a = 15, sa = 40
a = 15, sa = 45
a = 15, sa = 50
a = 15, sa = 55
a = 15, sa = 60
This is useful for cases where a function needs to keep some state between invocations, and you don't want to use global variables. Beware, however, this feature should be used very sparingly - it makes your code not thread-safe and harder to understand.
(2) is used widely as an "access control" feature. If you have a .c file implementing some functionality, it usually exposes only a few "public" functions to users. The rest of its functions should be made static, so that the user won't be able to access them. This is encapsulation, a good practice.
Quoting Wikipedia:
In the C programming language,
staticis used with global variables and functions to set their scope to the containing file. In local variables,staticis used to store the variable in the statically allocated memory instead of the automatically allocated memory. While the language does not dictate the implementation of either type of memory, statically allocated memory is typically reserved in data segment of the program at compile time, while the automatically allocated memory is normally implemented as a transient call stack.
See here and here for more details.
And to answer your second question, it's not like in C#.
In C++, however, static is also used to define class attributes (shared between all objects of the same class) and methods. In C there are no classes, so this feature is irrelevant.
Additionally, in C, static can be used in array declarators to specify minimum size of the array (non-function array declarators cannot use this keyword). Consider this declaration:
void func(int foo[static 42]);
The function func() takes an array of at least 42 elements.
Note that C++ does not support this use of the static keyword.
There is one more use not covered here, and that is as part of an array type declaration as an argument to a function:
int someFunction(char arg[static 10])
{
...
}
In this context, this specifies that arguments passed to this function must be an array of type char with at least 10 elements in it. For more info see my question here.
microcontroller - Concept of the static keyword from the perspective of embedded C - Electrical Engineering Stack Exchange
The static keyword and its various uses in C++ - Stack Overflow
programming languages - False friends? Keyword "static" in C compared to C++, C# and Java - Software Engineering Stack Exchange
What does Static keyword do in C++?
Videos
I don't really understand the use of static keyword.
I get it that it's use to limit the scope of the variable to a particular module, but it's not the same for any variables defined inside a function for example? Won't you just have that variable declared while the function is running and then the resource is freed once the function is finished?
Why do we use static keyword for global variables? What's the use of this static in embedded systems?
Thank you!
Usually, you will see the static keyword in these places:
- A static variable inside a function keeps its value between invocations.
- A static global variable or function is "seen" only in the file in which it's declared.
(1) is the more foreign topic if you're a newbie, so here's an example:
#include <stdio.h>
void foo()
{
int a = 10;
static int sa = 10;
a += 5;
sa += 5;
printf("a = %d, sa = %d\n", a, sa);
}
int main()
{
int i;
for (i = 0; i < 10; ++i)
foo();
}
This prints:
a = 15, sa = 15
a = 15, sa = 20
a = 15, sa = 25
a = 15, sa = 30
a = 15, sa = 35
a = 15, sa = 40
a = 15, sa = 45
a = 15, sa = 50
a = 15, sa = 55
a = 15, sa = 60
This is useful for cases where a function needs to keep some state between invocations, and you don't want to use global variables. Beware, however, this feature should be used very sparingly - it makes your code not thread-safe and harder to understand.
(2) is used widely as an "access control" feature. If you have a .c file implementing some functionality, it usually exposes only a few "public" functions to users. The rest of its functions should be made static, so that the user won't be able to access them. This is encapsulation, a good practice.
Quoting Wikipedia:
In the C programming language,
staticis used with global variables and functions to set their scope to the containing file. In local variables,staticis used to store the variable in the statically allocated memory instead of the automatically allocated memory. While the language does not dictate the implementation of either type of memory, statically allocated memory is typically reserved in data segment of the program at compile time, while the automatically allocated memory is normally implemented as a transient call stack.
See here and here for more details.
And to answer your second question, it's not like in C#.
In C++, however, static is also used to define class attributes (shared between all objects of the same class) and methods. In C there are no classes, so this feature is irrelevant.
Additionally, in C, static can be used in array declarators to specify minimum size of the array (non-function array declarators cannot use this keyword). Consider this declaration:
void func(int foo[static 42]);
The function func() takes an array of at least 42 elements.
Note that C++ does not support this use of the static keyword.
The keyword 'static' in C has two fundamentally different meanings.
Limiting Scope
In this context, 'static' pairs up with 'extern' to control the scope of a variable or function name. Static causes the variable or function name to be available only within a single compilation unit and only available to code that exists after the declaration/definition within the compilation unit text.
This limitation itself really only means something if and only if you have more than one compilation unit in your project. If you only have one compilation unit, then it still does things but those effects are mostly pointless (unless you like digging into object files to read what the compiler generated.)
As noted, this keyword in this context pairs with the keyword 'extern', which does the opposite -- by making the variable or function name linkable with the same name found in other compilation units. So you can look at 'static' as requiring the variable or name to be found within the current unit of compilation, while 'extern' permits cross-compilation unit linkage.
Static Lifetime
Static lifetime means that the variable exists throughout the duration of the program (however long that is.) When you use 'static' to declare/define a variable within a function, it means that the variable is created sometime prior to its first usage (which means, every time I've experienced it, that the variable is created before main() starts) and isn't destroyed afterwards. Not even when the function's execution is completed and it returns to its caller. And just like static lifetime variables declared outside of functions, they are initialized at the same moment -- before main() starts -- to a semantic zero (if no initialization is provided) or to a specified explicit value, if given.
This is different from 'auto' type function variables, which are created new (or, as-if new) each time the function is entered and then are destroyed (or, as-if they were destroyed) when the function exits.
Unlike the impact of applying 'static' on a variable definition outside of a function, which directly impacts its scope, declaring a function variable (within a function body, obviously) as 'static' has no impact on its scope. The scope is determined by the fact that it was defined within a function body. Static lifetime variables defined within functions have the same scope as other 'auto' variables defined within function bodies -- function scope.
Summary
So the 'static' keyword has different contexts with what amounts to "very different meanings." The reason it was used in two ways, like this, was to avoid using another keyword. (There was a long discussion about it.) It was felt that programmers could tolerate the use and the value of avoiding yet another keyword in the language was more important (than arguments otherwise.)
(All variables declared outside of functions have static lifetime and don't need the keyword 'static' to make that true. So this kind of freed up the keyword to be used there to mean something entirely different: 'visible only in a single compilation unit.' It's a hack, of sorts.)
Specific Note
static volatile unsigned char PORTB @ 0x06;
The word 'static' here should be interpreted to mean that the linker won't attempt to match up multiple occurrences of PORTB that may be found in more than one compilation unit (assuming your code has more than one.)
It uses a special (non-portable) syntax to specify the "location" (or the label's numeric value which is usually an address) of PORTB. So the linker is given the address and doesn't need to find one for it. If you had two compilation units using this line, they'd each wind up pointing to the same place, anyway. So there's no need to label it 'extern', here.
Had they used 'extern' it might pose a problem. The linker would then be able to see (and would attempt to match up) multiple references to PORTB found in multiple compilations. If all of them specify an address like this, and the addresses are NOT the same for some reason [mistake?], then what's it supposed to do? Complain? Or? (Technically, with 'extern' the rule of thumb would be that only ONE compilation unit would specify the value and the others should not.)
It's just easier to label it as 'static', avoiding making the linker worry about conflicts, and simply put the blame for any mistakes for mis-matched addresses upon whomever changed the address to something it shouldn't be.
Either way, the variable is treated as having a 'static lifetime.' (And 'volatile'.)
A declaration is not a definition, but all definitions are declarations
In C, a definition creates an object. It also declares it. But a declaration does not usually (see bullet note below) create an object.
The following are definitions and declarations:
static int a;
static int a = 7;
extern int b = 5;
extern int f() { return 10; }
The following are not definitions, but are only declarations:
extern int b;
extern int f();
Note that the declarations do not create an actual object. They only declare the details about it, which the compiler can then use to help generate correct code and to provide warning and error messages, as appropriate.
Above, I say "usually," advisedly. In some cases, a declaration can create an object and is therefore promoted to a definition by the linker (never by the compiler.) So even in this rare case, the C compiler still thinks the declaration is only a declaration. It is the linker phase that makes any necessary promotions of some declaration. Keep this carefully in mind.
In the above examples, should it turn out there are only declarations for an "extern int b;" in all the linked compilation units, then the linker is charged with the responsibility to create a definition. Be aware that this is a link-time event. The compiler is completely unaware, during compilation. It can only be determined at link-time, if a declaration of this type most be promoted.
The compiler is aware that "static int a;" cannot be promoted by the linker at link-time, so this actually is a definition at compile-time.
statics are not visible outside of the current compilation unit, or "translation unit". This is not the same as the same file.
Notice that you include the header file into any source file where you may need the variables declared in the header. This inclusion makes the header file a part of the current translation unit and (an instance of) the variable visible inside it.
Variables:
static variables exist for the "lifetime" of the translation unit that it's defined in, and:
- If it's in a namespace scope (i.e. outside of functions and classes), then it can't be accessed from any other translation unit. This is known as "internal linkage" or "static storage duration". (Don't do this in headers except for
constexpr. Anything else, and you end up with a separate variable in each translation unit, which is crazy confusing) - If it's a variable in a function, it can't be accessed from outside of the function, just like any other local variable. (this is the local they mentioned)
- class members have no restricted scope due to
static, but can be addressed from the class as well as an instance (likestd::string::npos). [Note: you can declare static members in a class, but they should usually still be defined in a translation unit (cpp file), and as such, there's only one per class]
locations as code:
static std::string namespaceScope = "Hello";
void foo() {
static std::string functionScope= "World";
}
struct A {
static std::string classScope = "!";
};
Before any function in a translation unit is executed (possibly after main began execution), the variables with static storage duration (namespace scope) in that translation unit will be "constant initialized" (to constexpr where possible, or zero otherwise), and then non-locals are "dynamically initialized" properly in the order they are defined in the translation unit (for things like std::string="HI"; that aren't constexpr). Finally, function-local statics will be initialized the first time execution "reaches" the line where they are declared. All static variables all destroyed in the reverse order of initialization.
The easiest way to get all this right is to make all static variables that are not constexpr initialized into function static locals, which makes sure all of your statics/globals are initialized properly when you try to use them no matter what, thus preventing the static initialization order fiasco.
T& get_global() {
static T global = initial_value();
return global;
}
Be careful, because when the spec says namespace-scope variables have "static storage duration" by default, they mean the "lifetime of the translation unit" bit, but that does not mean it can't be accessed outside of the file.
Functions
Significantly more straightforward, static is often used as a class member function, and only very rarely used for a free-standing function.
A static member function differs from a regular member function in that it can be called without an instance of a class, and since it has no instance, it cannot access non-static members of the class. Static variables are useful when you want to have a function for a class that definitely absolutely does not refer to any instance members, or for managing static member variables.
struct A {
A() {++A_count;}
A(const A&) {++A_count;}
A(A&&) {++A_count;}
~A() {--A_count;}
static int get_count() {return A_count;}
private:
static int A_count;
}
int main() {
A var;
int c0 = var.get_count(); //some compilers give a warning, but it's ok.
int c1 = A::get_count(); //normal way
}
A static free-function means that the function will not be referred to by any other translation unit, and thus the linker can ignore it entirely. This has a small number of purposes:
- Can be used in a cpp file to guarantee that the function is never used from any other file.
- Can be put in a header and every file will have it's own copy of the function. Not useful, since inline does pretty much the same thing.
- Speeds up link time by reducing work
- Can put a function with the same name in each translation unit, and they can all do different things. For instance, you could put a
static void log(const char*) {}in each cpp file, and they could each all log in a different way.
In order to clarify the question, I would rather categorize the usage of 'static' keyword in three different forms:
(A). variables
(B). functions
(C). member variables/functions of classes
the explanation follows below for each of the subheadings:
(A) 'static' keyword for variables
This one can be little tricky however if explained and understood properly, it's pretty straightforward.
To explain this, first it is really useful to know about the scope, duration and linkage of variables, without which things are always difficult to see through the murky concept of static keyword
1. Scope : Determines where in the file, the variable is accessible. It can be of two types: (i) Local or Block Scope. (ii) Global Scope
2. Duration : Determines when a variable is created and destroyed. Again it's of two types: (i) Automatic Storage Duration (for variables having Local or Block scope). (ii) Static Storage Duration (for variables having Global Scope or local variables (in a function or a in a code block) with static specifier).
3. Linkage: Determines whether a variable can be accessed (or linked ) in another file. Again ( and luckily) it is of two types: (i) Internal Linkage (for variables having Block Scope and Global Scope/File Scope/Global Namespace scope) (ii) External Linkage (for variables having only for Global Scope/File Scope/Global Namespace Scope)
Let's refer an example below for a better understanding of plain global and local variables (no local variables with static storage duration) :
//main file
#include <iostream>
int global_var1; //has global scope
const global_var2(1.618); //has global scope
int main()
{
//these variables are local to the block main.
//they have automatic duration, i.e, they are created when the main() is
// executed and destroyed, when main goes out of scope
int local_var1(23);
const double local_var2(3.14);
{
/* this is yet another block, all variables declared within this block
have a local scope limited within this block. */
// all variables declared within this block too have automatic duration, i.e,
/*they are created at the point of definition within this block,
and destroyed as soon as this block ends */
char block_char1;
int local_var1(32) //NOTE: this has been re-declared within the block,
//it shadows the local_var1 declared outside
std::cout << local_var1 <<"\n"; //prints 32
}//end of block
//local_var1 declared inside goes out of scope
std::cout << local_var1 << "\n"; //prints 23
global_var1 = 29; //global_var1 has been declared outside main (global scope)
std::cout << global_var1 << "\n"; //prints 29
std::cout << global_var2 << "\n"; //prints 1.618
return 0;
} //local_var1, local_var2 go out of scope as main ends
//global_var1, global_var2 go out of scope as the program terminates
//(in this case program ends with end of main, so both local and global
//variables go out of scope together
Now comes the concept of Linkage. When a global variable defined in one file is intended to be used in another file, the linkage of the variable plays an important role.
The Linkage of global variables is specified by the keywords: (i) static , and, (ii) extern
( Now you get the explanation )
static keyword can be applied to variables with local and global scope, and in both cases, they mean different things. I will first explain the usage of 'static' keyword in variables with global scope ( where I also clarify the usage of keyword 'extern') and later the usage for those with local scope.
1. Static Keyword for variables with global scope
Global variables have static duration, meaning they don't go out of scope when a particular block of code (e.g main() ) in which it is used ends . Depending upon the linkage, they can be either accessed only within the same file where they are declared (for static global variable), or outside the file even outside the file in which they are declared (extern type global variables)
In the case of a global variable having extern specifier, and if this variable is being accessed outside the file in which it has been initialized, it has to be forward declared in the file where it's being used, just like a function has to be forward declared if it's definition is in a file different from where it's being used.
In contrast, if the global variable has static keyword, it cannot be used in a file outside of which it has been declared.
(see example below for clarification)
eg:
//main2.cpp
static int global_var3 = 23; /*static global variable, cannot be
accessed in any other file */
extern double global_var4 = 71; /*can be accessed outside this file linked to main2.cpp */
int main() { return 0; }
main3.cpp
//main3.cpp
#include <iostream>
int main()
{
extern int gloabl_var4; /*this variable refers to the gloabal_var4
defined in the main2.cpp file */
std::cout << global_var4 << "\n"; //prints 71;
return 0;
}
now any variable in c++ can be either a const or a non-const and for each 'const-ness' we get two cases of default c++ linkage, in case none is specified:
(i) If a global variable is non-const, its linkage is extern by default, i.e, the non-const global variable can be accessed in another .cpp file by forward declaration using the extern keyword (in other words, non const global variables have external linkage ( with static duration of course)). Also, usage of extern keyword in the original file where it has been defined is redundant. In this case, to make a non-const global variable inaccessible to external file, use the specifier 'static' before the type of the variable.
(ii) If a global variable is const, its linkage is static by default, i.e a const global variable cannot be accessed in a file other than where it is defined, (in other words, const global variables have internal linkage (with static duration of course)). Also, usage of static keyword to prevent a const global variable from being accessed in another file is redundant. Here, to make a const global variable have an external linkage, use the specifier 'extern' before the type of the variable
Here's a summary of global scope variables with various linkages
//globalVariables1.cpp
// defining uninitialized variables
int globalVar1; // uninitialized global variable with external linkage
static int globalVar2; // uninitialized global variable with internal linkage
const int globalVar3; // error, since const variables must be initialized upon declaration
const int globalVar4 = 23; //correct, but with static linkage (cannot be accessed outside the file where it has been declared*/
extern const double globalVar5 = 1.57; //this const variable can be accessed outside the file where it has been declared
Next, we investigate how the above global variables behave when accessed in a different file.
//using_globalVariables1.cpp (eg for the usage of global variables above)
// Forward declaration via extern keyword:
extern int globalVar1; // correct since globalVar1 is not a const or static
extern int globalVar2; //incorrect since globalVar2 has internal linkage
extern const int globalVar4; /* incorrect since globalVar4 has no extern
specifier, limited to internal linkage by
default (static specifier for const variables) */
extern const double globalVar5; /*correct since in the previous file, it
has extern specifier, no need to initialize the
const variable here, since it has already been
legitimately defined previously */
- Static Keyword for variables with Local Scope
Updates (August 2019) on static keyword for variables in local scope
This further can be subdivided in two categories :
(i) static keyword for variables within a function block, and (ii) static keyword for variables within an unnamed local block.
(i) static keyword for variables within a function block.
Earlier, I mentioned that variables with local scope have automatic duration, i.e they come to exist when the block is entered ( be it a normal block, be it a function block) and cease to exist when the block ends, long story short, variables with local scope have automatic duration and automatic duration variables (and objects) have no linkage meaning they are not visible outside the code block.
If static specifier is applied to a local variable within a function block, it changes the duration of the variable from automatic to static and its lifetime is the entire duration of the program which means it has a fixed memory location and its value is initialized only once prior to program start up as mentioned in cpp reference(initialization should not be confused with assignment)
lets take a look at an example.
//localVarDemo1.cpp
int localNextID()
{
int tempID = 1; //tempID created here
return tempID++; //copy of tempID returned and tempID incremented to 2
} //tempID destroyed here, hence value of tempID lost
int newNextID()
{
static int newID = 0;//newID has static duration, with internal linkage
return newID++; //copy of newID returned and newID incremented by 1
} //newID doesn't get destroyed here :-)
int main()
{
int employeeID1 = localNextID(); //employeeID1 = 1
int employeeID2 = localNextID(); // employeeID2 = 1 again (not desired)
int employeeID3 = newNextID(); //employeeID3 = 0;
int employeeID4 = newNextID(); //employeeID4 = 1;
int employeeID5 = newNextID(); //employeeID5 = 2;
return 0;
}
Looking at the above criterion for static local variables and static global variables, one might be tempted to ask, what the difference between them could be. While global variables are accessible at any point within the code (in the same as well as different translation units depending upon the const-ness and extern-ness), a static variable defined within a function block is not directly accessible. The variable has to be returned by the function value or reference. Lets demonstrate this by using an example:
//localVarDemo2.cpp
//static storage duration with global scope
//note this variable can be accessed from outside the file
//in a different compilation unit by using `extern` specifier
//which might not be desirable for certain use cases.
static int globalId = 0;
int newNextID()
{
static int newID = 0;//newID has static duration, with internal linkage
return newID++; //copy of newID returned and newID incremented by 1
} //newID doesn't get destroyed here
int main()
{
//since globalId is accessible we use it directly
const int globalEmployee1Id = globalId++; //globalEmployeeId1 = 0;
const int globalEmployee2Id = globalId++; //globalEmployeeId1 = 1;
//const int employeeID1 = newID++; //this will lead to compilation error since newID++ is not accessible direcly.
int employeeID2 = newNextID(); //employeeID3 = 0;
int employeeID2 = newNextID(); //employeeID3 = 1;
return 0;
}
More explanation about choice of static global and static local variables could be found on this stackoverflow thread
(ii) static keyword for variables within an unnamed local block.
static variables within a local block (not a function block) cannot be accessed outside the block once the local block goes out of scope. No caveats to this rule.
//localVarDemo3.cpp
int main()
{
{
const static int static_local_scoped_variable {99};
}//static_local_scoped_variable goes out of scope
//the line below causes compilation error
//do_something is an arbitrary function
do_something(static_local_scoped_variable);
return 0;
}
C++11 introduced the keyword constexpr which guarantees the evaluation of an expression at compile time and allows the compiler to optimize the code. Now if the value of a static const variable within a scope is known at compile time, the code is optimized similarly to the one with constexpr. Here's a small example
I recommend readers also to look up the difference between constexprand static const for variables in this stackoverflow thread.
this concludes my explanation for the static keyword applied to variables.
B. 'static' keyword used for functions
in terms of functions, the static keyword has a straightforward meaning. Here, it refers to linkage of the function Normally all functions declared within a cpp file have external linkage by default, i.e a function defined in one file can be used in another cpp file by forward declaration.
using a static keyword before the function declaration limits its linkage to internal , i.e a static function cannot be used within a file outside of its definition.
C. Static Keyword used for member variables and functions of classes
1. 'static' keyword for member variables of classes
I start directly with an example here
#include <iostream>
class DesignNumber
{
private:
static int m_designNum; //design number
int m_iteration; // number of iterations performed for the design
public:
DesignNumber() { } //default constructor
int getItrNum() //get the iteration number of design
{
m_iteration = m_designNum++;
return m_iteration;
}
static int m_anyNumber; //public static variable
};
int DesignNumber::m_designNum = 0; // starting with design id = 0
// note : no need of static keyword here
//causes compiler error if static keyword used
int DesignNumber::m_anyNumber = 99; /* initialization of inclass public
static member */
enter code here
int main()
{
DesignNumber firstDesign, secondDesign, thirdDesign;
std::cout << firstDesign.getItrNum() << "\n"; //prints 0
std::cout << secondDesign.getItrNum() << "\n"; //prints 1
std::cout << thirdDesign.getItrNum() << "\n"; //prints 2
std::cout << DesignNumber::m_anyNumber++ << "\n"; /* no object
associated with m_anyNumber */
std::cout << DesignNumber::m_anyNumber++ << "\n"; //prints 100
std::cout << DesignNumber::m_anyNumber++ << "\n"; //prints 101
return 0;
}
In this example, the static variable m_designNum retains its value and this single private member variable (because it's static) is shared b/w all the variables of the object type DesignNumber
Also like other member variables, static member variables of a class are not associated with any class object, which is demonstrated by the printing of anyNumber in the main function
const vs non-const static member variables in class
(i) non-const class static member variables In the previous example the static members (both public and private) were non constants. ISO standard forbids non-const static members to be initialized in the class. Hence as in previous example, they must be initialized after the class definition, with the caveat that the static keyword needs to be omitted
(ii) const-static member variables of class this is straightforward and goes with the convention of other const member variable initialization, i.e the const static member variables of a class can be initialized at the point of declaration and they can be initialized at the end of the class declaration with one caveat that the keyword const needs to be added to the static member when being initialized after the class definition.
I would however, recommend to initialize the const static member variables at the point of declaration. This goes with the standard C++ convention and makes the code look cleaner
for more examples on static member variables in a class look up the following link from learncpp.com http://www.learncpp.com/cpp-tutorial/811-static-member-variables/
2. 'static' keyword for member function of classes
Just like member variables of classes can be static, so can member functions of classes. Normal member functions of classes are always associated with a object of the class type. In contrast, static member functions of a class are not associated with any object of the class, i.e they have no *this pointer.
Secondly since the static member functions of the class have no *this pointer, they can be called using the class name and scope resolution operator in the main function (ClassName::functionName(); )
Thirdly static member functions of a class can only access static member variables of a class, since non-static member variables of a class must belong to a class object.
for more examples of static member functions in a class, look up the following link from learncpp.com
http://www.learncpp.com/cpp-tutorial/812-static-member-functions/
Update April 2021: static keyword and lambda expressions
Lambda expressions follow normal name lookup rules and hence the scope (local vs global) and storage class (static vs automatic) affect how the variables are available to the lambda expressions
- non-static global variable is available to lambda expression within a local scope.
//global member
int i=10;
int main(){
[]{std::cout << i;}();
//prints 10
}
- Non-Static local variable is not available to lambda expression that appears within the same or a different scope. In this case, as we're mostly used to, the variables have to be captured by value or by reference
int main(){
int i{11};
[]{std::cout << i;}(); //compiler error
[i]{std::cout << i;}(); //capture by value; correct
//or
[&i]{std::cout << i;}(); //capture by reference; correct
}
- Static variables locally scoped static variables can be captured by lambda expressions within the same or lower/child scope
int main(){
static int i{12};
[]{std::cout << i;}(); //prints 12
{
[]{std::cout << i;}();//also prints 12
}
}
However static variables in unnamed scope cannot be accessed outside the scope as explained previously
I have a book about the design of C++ by Bjarne Stroustrup (the inventor of C++). I don't have it right here so I can't lookup the exact quote right now, but in it he admits that when he added static to C++, he didn't fully understand what it meant in C. So that's why in C++ it has a different meaning than in C.
Java and C# inherited the meaning from C++.
Notably, C++ has both uses of static, and I think there's a third somewhere.
Generally, I think that the C use of static does not correspond at all to any English usage of the word, whereas I think that static as a static member variable, for example, makes a lot more sense.
Remember that as a language designer, you have a fair incentive to introduce fewer keywords into the language, to disallow less code- especially when you're trying to be source-compatible with C, as in C++, and the static keyword already existed, so they couldn't break any C programs trying to compile as C++ by re-using it.
Edit: I knew there was a third. C has function-level static variables. The static member is just a scoped version of this functionality. Therefore, both uses of static originate from C.