For a static variable defined within a C function, like below:
int f1()
{
static int var2 = 42;
var2 ;
printf("var2=%d\n", var2);
}
The var2
will be stored in the bss
segment:
0000000000004014 l O .data 0000000000000004 var2.2316
There are 2 aspects about the var2
:
- Its lifetime is the same as the whole program.
- But its scope is limited to within
f1()
.
The bss
section is meant for uninitialized global data. While the data
section is meant for initialized global data. The var2
lives in bss
so it must be global in a sense.
I think the reason that var2
can only be accessed within f1()
is just some syntactical rule placed by the compiler. If we iterate through the bss
section, the var2
must be accessible from outside the f1()
. Am I right on this? Thanks.
CodePudding user response:
Well you have raw access to memory, so the world's your oyster, but their limited access scope is exactly the whole point of using static local variables.
They're global state with controlled access, so you can apply local reasoning.
If you can access them externally, then local reasoning goes out the door. At that point, one should think: why not just use a regular global?
CodePudding user response:
Two execution environments are defined: freestanding and hosted. In both cases, program startup occurs when a designated C function is called by the execution environment. All objects with static storage duration shall be initialized (set to their initial values) before program startup. The manner and timing of such initialization are otherwise unspecified. Program termination returns control to the execution environment.
An object whose identifier is declared without the storage-class specifier _Thread_local, and either with external or internal linkage or with the storage-class specifier static, has static storage duration. Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup.
Your static local variable has static storage duration and will be initialized before program execution starts (ie before main
is called). You can access it via a pointer to it. The pointer can be only obtained by calling the function.
int *func()
{
static int x;
return &x
}
CodePudding user response:
The following is more or less hacker stuff, in addition to other answers, not from the viewpoint of a language lawyer.
I think the reason that
var2
can only be accessed withinf1()
is just some syntactical rule placed by the compiler.
To be picky, this is true only if the compiler is compliant to the standard. ;-) It is the standard that defines the rule. The technical term is "scope".
If we iterate through the
bss
section, thevar2
must be accessible from outside the f1(). Am I right on this?
Yes. The section exists as long as the program runs. You can use a pointer into this section and access any variable living there. This holds true for the data
section, too, of course.
You can also use a pointer to access any dynamic variable. Commonly these are allocated on the stack. To get a grip on a specific value can be quite tricky, though.
But all these accesses are application specific, compiler dependent, and system dependent, at least. You will probably break some rules. But in principle, nothing can stop you.
The
bss
section is meant for uninitialized global data. While thedata
section is meant for initialized global data.
This is only true if you mean "explicitly initialized to non-zero values".
Both sections are initialized before main()
starts. All values in bss
are zeroed, and all values in data
are set to their non-zero values. A variable explicitly initialized to a zero value will commonly be allocated in bss
.
The reason for the existence of separate sections is to save space in the executable. The bss
section is commonly not stored, it is only defined. It does not makes sense to store a whole bunch of zeroes, the startup code will zero the complete section.
The var2 lives in bss
var2
does not live in the bss
segment, but in the data
segment, as the cutout clearly shows. Your var
is initialized with 42, which is apparently non-zero.
CodePudding user response:
There are 2 aspects about the var2:
- Its lifetime is the same as the whole program.
- But its scope is limited to within
f1()
.
Yes and no. Lifetime is a property of objects. Scope is a property of identifiers (names). That the scope of var2
is from its declaration in f1()
to the end of the function is about the region of the source wherein that name identifies the object in question. On the other hand, that the lifetime of the object identified by var2
inside that scope is the same as the whole program's is about the object itself.
The bss section is meant for uninitialized global data. While the data section is meant for initialized global data. The var2 lives in bss so it must be global in a sense.
Be very careful about trying to infer language semantics from implementation details. It is very easy to get that wrong, and very hard to get it right in all details. In this particular case, the object in question is global in exactly the sense that its lifetime is the same as the whole program's, which you already knew.
For the record, "global" is not a C-language term. When people say "global variable" in C context, they usually mean a variable more properly described as having external linkage, which necessarily identifies an object having static storage duration (i.e. the whole execution of the program). That's not what you're looking at in the case of var2
.
I think the reason that
var2
can only be accessed withinf1()
is just some syntactical rule placed by the compiler.
More or less yes. The object can be accessed by name only within the scope of that name. This is among the semantic rules of the C language. It is essentially the definition of "scope".
If we iterate through the
bss
section, thevar2
must be accessible from outside thef1()
. Am I right on this?
How do you propose to "iterate through the bss
section"? In the first place, that's a characteristic of some executable file formats, not a runtime characteristic of the program. But perhaps you mean "iterate through memory", but even then, C does not define a way to do that.
With that said, if f1()
published a pointer to its var2
variable, via an out variable, for example, that pointer could indeed be used outside the function to access that object. Like this, for example:
int f1(int **pptr) {
static int var2 = 42;
*pptr = &var2;
var2 ;
return printf("var2=%d\n", var2);
}
// ...
void other_function() {
int *ptr;
int res = f1(&ptr);
printf("%d\n", *ptr);
}