Reputation: 316
I realize that it retains the value after going out of scope (but becomes inaccessible), but I have a few questions.
When people say it is inaccessible outside of the scope, it just means that you cannot alter the value (it will error) outside of its identifying scope?
I was thinking about this code:
#include "iostream"
void staticExample();
int main()
{
staticExample();
return 0;
}
void staticExample()
{
for (int i = 1; i <= 10; ++i)
{
static int number = 1;
std::cout << number << "\n";
++number;
}
}
and I thought to myself, that in every iteration of the loop, I am setting the 'number' variable to 1. As I first expected though, it printed 1, 2, 3.. 10. Does the compiler recognize that the line setting it to 1 was a declaration and ignores its "change"?
Upvotes: 6
Views: 798
Reputation: 21259
A static
variable (this also is valid for static
class
members) gets initialized only once - globally. Even the first run through the scope that declares the initialization will usually ignore the initialization, though there may be some compiler out there that does it differently - so it's compiler-dependent.
The reason: the initialization usually happens before your main()
function gets called and often will even be reflected in the executable/binary itself in that static data gets written there pre-initialized at link-time. This means that static
data most of the time will be valid even before the first piece of code (the parts of the C runtime that will call your main()
) gets to run.
Other than pointer/reference aliasing there would not be a way to access such a variable outside its immediate scope (the surrounding braces {}
), though.
From here:
6.7 Declaration statement
An implementation is permitted to perform early initialization of other block-scope variables with static or thread storage duration under the same conditions that an implementation is permitted to statically initialize a variable with static or thread storage duration in namespace scope (3.6.2).
Most implementations I have encountered during reverse-engineering appear to make use of this, in particular because the following also applies:
3.7.1 Static storage duration
If a variable with static storage duration has initialization or a destructor with side effects, it shall not be eliminated even if it appears to be unused, except that a class object or its copy/move may be eliminated as specified in 12.8.
... which means it makes sense to have static
behave similar to the way it did in C - i.e. initialize its contents up-front if the initialization was defined at compile-time.
Many compilers will otherwise initialize with zero or some magic number (for example in debug builds) when the variable was declared but not initialized at declaration-time.
Upvotes: 1
Reputation: 58500
The object comes to life once and so it is initialized once. Initialization is not assignment. (IINA? いい、な!)
Upvotes: 2
Reputation: 2344
Call staticExample twice and see what happens to your output. This will help you understand 'static storage' as it applies to local variables.
#include <iostream>
void staticExample()
{
static int number = 1;
for (int i = 1; i <= 10; ++i)
{
std::cout << number << "\n";
++number;
}
}
int main()
{
staticExample(); // begins counting at 1
staticExample(); // begins counting at 10
return 0;
}
Output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
I read a quote once that I liked, "You have stack storage and you have heap storage, but you also have another type of storage. It's called static and it's neither on the stack or in the heap." Not verbatim, but something similar to that.
Upvotes: 4
Reputation: 791431
When people say it is inaccessible outside of the scope, it just means that you cannot alter the value (it will error) outside of it's identifying scope?
No, that's not what scope means. When you use a name "outside of the scope" of something it means that that name won't resolve to the entity named inside the scope in question. The name might resolve to a different object or it might be an invalid name depending on the context.
So long as the object's lifetime has begun and hasn't ended the object could be altered by an expression outside of the scope of its variable by various means such as it's address being passed to another function where it is stored and subsequently this stored address is used to alter the object.
In your code example = 1
is an initializer, not an assignment. It is used when the variable is initialized which, as the object is declared static
, happens only the first time execution passes through the declaration statement.
Upvotes: 0
Reputation: 272467
It just means that code like this will result in a compiler error message:
{
static int x;
x = 5;
}
x = 6; // Compiler error here! We're outside the scope that x was declared in.
But that doesn't mean you can't access it. For example:
int *p = NULL;
{
static int x;
x = 5;
p = &x;
}
*p = 6; // This is fine
A static variable is only initialised once; the first time it's reached.
Upvotes: 0