Is there a specific term for the following type of C code? In my example, I want to increase the depth of scope for a small chunk of code within a function without having to use needless if/else/for statements so that I can re-declare a variable with the same name multiple times. eg:
void myfunc(void) {
int a = 0, b = 1;
{
int c;
c = 3;
printf("c is: %d", c);
}
a = 2;
{
int c = 5;
printf("c is %d", c);
}
}
What is the term used to describe how I just wrapped some code in curly braces and increased the scope depth so the rest of the function doesn't see the 'c' int?
Thanks!
Scope is defined as the area in which the object is active. There are five scopes in C. They are as follows.
Program Scope
These are the declarations at the top most layers. They are available up to the life of a program. All the functions have this scope. This is otherwise known as global scope.
File Scope
It has scope such that it may be accessed from that point to the end of the file.
void dummy(void) { }
// absence of static automatically gives program scope to `dummy()`
static void dummy(void) { }
// static keyword here gives function `dummy()` a file scope
Function Scope
Only labels have this scope. In this scope, they are active up to end of the function.
void printFun()
{
print:
printf(“i is less than j”);
}
int main()
{
int i=1,j=2;
if(i < j)
goto print;
}
This code will be flagged error by the compiler saying that the label print is not known because labels have only function scope. If you have to jump unconditionally between the functions, you have to use setjmp/longjmp functions.
Block Scope
Declarations that are active up to the end of the block (where a block is defined as statements within { }). All the declarations inside the function have only block scope.
int fun(int a, int b)
{
int c;
{
int d;
}
// a, b, c, d all have block scope
}
As I have said, function scope applies only to labels. So should not be confused with block scope. The function arguments are treated as if they were declared at the beginning of the block with other variables (remember that the function body is also considered as a block within { }). So the function arguments have block scope (not function scope).
Local scope is general usage to refer the scope that is either function or block scope.
Prototype Scope
They are having the scope only inside the prototype declaration. This scope is interesting because the variable names are valid only in the declaration of prototype and does not conflict with other variable names. It exists for very little time and of less use and so goes unnoticed.
int add(int a, float b);
Here the variables a and b are said to have prototype scope.
Selecting Minimal Scope
When a name has to be resolved, that name is searched in the minimal scope, and if that is not available, it is searched at higher levels of scope. So, if a variable has to be declared, you have to select a minimal scope possible. If you can limit your scope, that increases the efficiency, readability and maintainability of your program. If you want a variable which is not useful outside a block, declare it inside the block and not in the outer ones. Similarly, if you want a variable whose value will be accessed only within the function but has to retain the value between the function calls, opt for static variable to a global one.
I'd say you are introducing a new local scope, or a nested scope, or a block.
This becomes seriously important in C++ when you take active advantage of this:
{
std::lock_guard<std::mutex> lk(my_mutex);
do_critical_stuff(); // might throw exception?
}
// the lock is released automagically!
But even in C it's good practice to only use variables locally where they're needed and not bleed them into unnecessarily wide scopes.
The term is the scope.
K&R2 defines the word scope as
A name also has a scope, which is the region of the program in which
it is known
Scope is the word that refers to the visibility of an identifier.
Related
In K&R it is stated:
An automatic variable declared and initialized in a block is
initialized each time the block is entered.
Here is a code snippet solely for communicating the question. Two options are shown; declaring error_string in the main function body and declaring it within the block scope of an if().
The question is, if the option2 declaration is used, can the compiler be relied upon to optimize the act of repeatedly instantiating the string?
It may make the code more readable to declare variables closest to where they are used. Limiting their scope as much as possible is perhaps a good design practice. Could doing so have any appreciable detriment to efficiency?
#define MAX_ERROR_STRING_LEN 1024
void process_results(int *results, int n_results)
{
int i;
char error_string[MAX_ERROR_STRING_LEN]; //option1
for (i = 0; i < n_results; i++) //suppose n_results == 1 million, 98% "FAILURE"
{
if (results[i] == FAILURE)
{
char error_string[MAX_ERROR_STRING_LEN];//option2
get_error_string(error_string, MAX_ERROR_STRING_LEN - 1);
fprintf(debug_log, "Error: %s\n", error_string);
}
}
}
on a related note, should this be avoided:
for (i = 0; i < strlen(error_string); i++)
printf("%c", error_string[i]);
in favor of:
int len = strlen(error_string);
for (i = 0; i < len; i++)
printf("%c", error_string[i]);
or will that be optimized despite dependence on run-time data?
Edit - no changes just adding research:
I think this confirms the block scoped variables are repeatedly created and destroyed (for all intents and purposes to the programmer):
A.4.1 Storage Class There are two storage classes: automatic and
static. Several keywords, together with the context of an object's
declaration, specify its storage class. Automatic objects are local to
a block (Par.9.3), and are discarded on exit from the block.
Most of the rest seems to refer to lexical scope rather than linkage:
A.11.1 Lexical Scope ... The scope of a parameter of a function
definition begins at the start of the block defining the function, and
persists through the function; the scope of a parameter in a function
declaration ends at the end of the declarator. The scope of an
identifier declared at the head of a block begins at the end of its
declarator, and persists to the end of the block.
Regarding Lexical scope?:
The scope of a name is the part of the program within which the name
can be used. For an automatic variable declared at the beginning of a
function, the scope is the function in which the name is declared.
Local variables of the same name in different functions are unrelated.
The same is true of the parameters of the function, which are in
effect local variables.
also
A name also has a scope, which is the region of the program in which
it is known, and a linkage, which determines whether the same name in
another scope refers to the same object or function. Scope and linkage
are discussed in Par.A.11.
The local variable error_string is not initialized, there is no overhead in declaring it with block scope instead of function scope. Some compilers might allocate temporary stack space for error_string upon entering the block scope and deallocate it upon leaving this scope, which involves a single instruction in both cases, but most compilers will allocate space for all local variables in a single step at the beginning of the function.
Since you are concerned with efficiency, note that both code fragments posted to print a string are very inefficient compared to this:
fputs(error_string, stdout);
The output of the following code is 0.
int account=2;
int main()
{
static int account;
printf("%d",account);
return 0;
}
Why it picked static variable over global variable? Because what I understand is that both global and static variables are stored in the heap and not in function stack , right? So what method it uses to use select one over another?
If multiple variables exist with the same name at multiple scopes, the one in the innermost scope is the one that is accessible. Variables at higher scope are hidden.
In this case you have account defined in main. This hides the variable named account declared at file scope. The fact that the inner variable inside main is declared static doesn't change that.
While the static declaration on a local variable means that it is typically stored in the same place as a global variable, that has no bearing on which is visible when the names are the same.
Consider this small self explaining program:
#include <stdio.h>
int bar = 123; // global variable, can be accessed from other source files
static int blark; // global variable, but can be accessed only in the same
// source file
void foo()
{
static int bar; // static variable : will retain it's value from
// one call of foo to the next
// most compilers will warn here:
// warning declaration of 'bar' hides global declaration
printf("foo() : bar = %d\n", bar); // won't use the global bar but the
// local static bar
bar++;
}
void quork()
{
int bar = 777; // local variable exists only during the execution of quork
// most compilers will warn here as well:
// warning declaration of 'bar' hides global declaration
printf("quork() : bar = %d\n", bar); // won't use the global bar but the
// local bar
bar++;
}
int main() {
foo();
foo();
printf("main() 1 : bar = %d\n", bar);
bar++;
quork();
quork();
foo();
printf("main() 2 : bar = %d\n", bar);
printf("blark = %d\n", blark);
}
Output:
foo() : bar = 0
foo() : bar = 1
main() 1 : bar = 123
quork() : bar = 777
quork() : bar = 777
foo() : bar = 2
main() 2 : bar = 124
blark = 0
Just to clarify for future readers, global and static variables are not stored in heap or stack memory.
https://www.geeksforgeeks.org/memory-layout-of-c-program/
They will either be stored in initialized data or uninitialized data.
Thats not the main question here, which was answered by dbush, but it is a misunderstanding in the original question.
Short answer: encapsulation.
static describes both lifetime and visibility of a variable, and its meaning changes depending on the context. My opinion is that it is one of the more useful and important language features for encapsulation in c. Ignoring the complex relationship to extern, here's a simplified description:
static variables defined at the file level have program lifetime and compilation unit visibility. This means all functions in a .c file can access/modify the variable, but other .c files won't know about the variable. This is super useful for making sure variables used across functions with a compilation unit don't accidentally link with variables in other compilation units. Personally, I highly recommend all file variables to be static by default. Only remove the static specifier if you really want another compilation unit to have access to it (although a getter function may be safer)
Variables declared static within a block scope (most importantly function scope) have program lifetime, and scope visibility. That means it functions as if you declared the variable globally in the file, but only code within that block scope can see it. It also means from one call to the next, the variable does not get destroyed and state can be transferred from call to call.
One really important difference with static variables is that they are default-initialized to zero. This differs from all other variables in c, and is the reason your program prints the value 0. Often times with trivial programs we don't notice the difference because the stack hasn't been polluted with variables yet, but it becomes critical for any program of size.
The most common use for this that I have seen is to enable one-time initialization within a scope. They are also extremely useful for synchronization primitives like pthread_mutex_t. One time I even implemented a state-machine with function-scope static variable.
an example:
int started;//oops, anybody in the entire program can change this value, especially with such a common name!
static int lastCall;
int callCount(void)
{
// This is default-initialized to 0
static int functionStaticVariable;
//Increment each time I'm called
++functionStaticVariable;
//tell the outside world that I'm the one who was called last
lastCall = 1;
//return (a copy of) my internal state.
return functionStaticVariable;
}
char *getSharedMemory(unsigned int bytes)
{
// Here I cannot see functionStaticVariable, but I can see globalVariable
//functionStaticVariable++; // this would cause a compilation failure
// static pointer is default-initialized to zero (i.e. NULL)
static char *sharedMemory;
if(sharedMemory == 0)
{
// This block only executes once, the first time the function is called.
// Actually this is a nice side-effect because it means if the function is never called we don't clutter the stack with unused memory
// Although we will probably never free this memory
sharedMemory = (char *)malloc(bytes);
}
// tell the outside world that this function has been called
lastCall = 2;//valid
//Woah, this is such a bad idea, but actually does _not_ return memory that gets invalidated
return sharedMemory;
}
Hopefully you can see with this pattern you could protect a variable by placing it inside a function and doing optional things like acquiring a mutex-lock in order to allocate the memory. You could even implement the double-lock pattern this way.
I secretly wish that all C++ programmers learned good c encapsulation, because actually the language really encourages it. You can do an incredible amount by placing only functions that need to communicate with each other together in a compilation unit. In a non-OOP language, this can be very powerful.
Full details of static and extern are described by https://en.cppreference.com/w/c/language/storage_duration.
The pragmatic reasoning behind why innermost variable decaration should be the one used: you're not always in control of what's outside your code. You want to be able to write a function that certainly works. If other programmers (say, in a larger team) could break your code just by the way they name variables in other parts of the code, programming would be more of a pain than it is now.
Following is the code, that I took as reference to understand how a sub scope (or) dummy scope (just {}) present within the function, impacts the structure of the stack frame.
#include <stdio.h>
int main()
{
int main_scope=0; /*Scope and life time of the variable is throughout main*/
{
//From below two statements I assume that there
//is no seperate "stack frame" created for just
//braces {}.So we are free access (scope exists) and
//modify (lifetime exists) the variable "main_scope"
//anywhere within main
main_scope++;
printf("main_scope++:(%d)\n",main_scope);
//I expected this statement to throw an error saying
//"Multiple definition for "main_scope".But it isn't????
int main_scope=2;
printf("Value of redefined main_scope:(%d)\n",main_scope);
}
printf("Finally main_scope in %s:(%d)\n",__FUNCTION__,main_scope);
return 0;
}
Sample output
main_scope++:(1)
Value of redefined main_scope:(2)
Finally main_scope in main:(1)
Based on the above behavior, I presume the following.
There is no stack frame creation for the scope {}.
By this way the auto variables, declared/defined in main and those within the sub scope {} share the same stack frame.
So the variables declared/defined in main are free to be accessed anywhere within the function (even within the sub scope).
On the other hand the variables declared/defined in the sub scope loses its scope out of the block.But its life time is valid as long as stack frame is present.
Question: If the above points are right, then why isn't the code failing when giving multiple definitions of the same variable, one within main and the other within {}.
The hardware stack is irrelevant here. It can grow only once for all local variables at function entry and shrink only once at function exit or it can grow and shrink every time a new local variable is defined and destroyed when the enclosing {} for it is left.
What's relevant is the "visibility" of variables.
int main_scope=0;
{
main_scope++;
printf("main_scope++:(%d)\n",main_scope);
// the main_scope variable that was assigned 0 is the most recent
// visible declaration of main_scope.
int main_scope=2;
// now, the previous declaration of main_scope is obscured by the new one,
// and so, you're going to access the new one
printf("Value of redefined main_scope:(%d)\n",main_scope);
}
printf("Finally main_scope in %s:(%d)\n",__FUNCTION__,main_scope);
// the previous scope inside {} is left, so, main_scope is going to be
// the one, to which we assigned 0
It is perfectly legal to define an object in an inner/sub-scope with the same name as in an outer/super-scope. The latter will be obscured for the duration of the {} scope.
Just for the reference, there are some other places, where variable definitions can occur, e.g. inside the first expression of the for(;;) statement: for (int i = 0; i < 10; i++) .... That variable i will only be visible inside the for's body, and you can hide it there as well by defining another i.
Local variable hides the outer variable main_scope.
int main()
{
int i=1;
{
int i=2;
printf("%d", i);
/* Whenever you use i here, it's always the local one that's used.
The outer i is hidden by the local i. But the local i will be deallocated
once the scope exits.*/
}
}
is perfectly legal in C. (Note that this is illegal in C++!)
In your example, certainly a stack frame is created for inner main_scope, but it'll be deallocated once program goes out that inner scope.
if a variable is defined in a block is it present in the block only or throughout the program?
for example
main()
{
int j=5;
{
int i=10
printf("%d",i);
}
printf("%d , %d ",i,j);
}
is it valid
main()
{
int j=5, *k;
{
int i=10
printf("%d",i);
}
k=&i
printf("%d , %d ",*k,j);
}
as variable remains in memory from the point of its declaration to the point wen function exits?
A non-global variable's scope is limited to the block it's defined in. Furthermore, for an automatic variable, once the block ends the variable's lifetime is over.
Consider this silly example:
void doit()
{
int *ps;
int *pa;
{
static int s = 1;
int a = 2;
ps = &s;
pa = &a;
}
// cannot access a or s here because they are out of scope
// *ps is okay because s is static so it's lifetime is not over
// *pa is not okay because a's lifetime ends at the end of the block
}
Your second printf line will not compile because i is not in scope.
It's only accessible within the block, so in your example the second printf() is illegal and will not compile.
Yes its scope is then limited to the block where it is located.
The scope of i is limited within the block where it is declared. In your case it is
{
int i=10
printf("%d",i);
}
Hence i is not accessible outside this scope
This question also relates to your question about local scope or an auto variable.
Scope can be defined as the module within which this variable is defined.
And a module may be a function or a file.
So you can declare an auto variable in a file - which would mean it can be accessed by every function in that file, or put another way - its scope is defined to be the file in this case.
If you declare the same variable as auto, but within a function, it would mean that it can only be accessed within that function - or its scope is defined to be the function in this case.
Think of auto as 'local' within a module (where module may be a function or a file).
In the example above, you have defined the scope by adding the braces, and therefore the scope of variable i is localised to within the braces, which is why you have limited access outside the braces.
Is the static keyword in C used only for limiting the scope of a variable to a single file?
I need to know if I understood this right. Please assume the following 3 files,
file1.c
int a;
file2.c
int b;
file3.c
static int c;
Now, if the 3 files are compiled together, then the variables "a" & "b" should have a global scope and can be accessed from any of the 3 files. But, variable "c" being static, can only be accessed from file3.c, right?
Does static have any other use in C ? (other than to limit the scope of a variable as shown above?)
The static keyword serves two distinct purposes in C, what I call duration (the lifetime of an object) and visibility (where you can use an object from). Keep in mind the C standard actually uses different words for these two concepts but I've found in teaching the language that it's best to use everyday terms to begin with.
When used at file level (outside of any function), it controls visibility. The duration of variables defined at file level are already defined as being the entire duration of the program so you don't need static for that.
Static variables at file level are invisible to anything outside the translation unit (the linker can't see it).
When used at function level (inside a function), it controls duration. That's because the visibility is already defined as being local to that function.
In that case, the duration of the variable is the entire duration of the program and the value is maintained between invocations of the function.
You are misusing the term "scope". static in C has absolutely nothing to do with scope.
Scope is the region where the name of an entity (variable, function, typename etc.) is visible. In C language "file scope" is the largest scope ever. For that reason, there's no point in limiting anything to a single file: there's simply nothing larger to limit. There's no such thing as "global scope" in C. The term "global scope" is sometimes used informally, but in that case it has the same meaning as "file scope".
Again, static in C has absolutely nothing to do with scope. static in C affects storage duration of an object and linkage of an identifier. When used with objects (variables) static gives the object static storage duration (i.e. the object exists as long as the program runs). And, when used with identifiers of non-local objects or functions, it gives them internal linkage, meaning that the same identifier refers to the same entity within a single translation unit (where the entity is defined), but not in other translation units.
static is also used within a function definition to define a variable which keeps its value between function calls. I found an example here. In contrast, variables which are created anew with each function call are called automatic.
An example to augment Kinopiko’s answer:
#include <stdio.h>
int foo() {
static int foo = 0;
return ++foo;
}
int main() {
printf("%i\n", foo()); // 1
printf("%i\n", foo()); // 2
}
This can be used for example to return a safe pointer to a local function variable. Or in Objective-C it’s sometimes used to guard against repeated class initialization:
- (void) initialize
{
static BOOL initialized = NO;
if (initialized)
return;
// …perform initialization…
initialized = YES;
}
A variable may have three kinds of storage:
In program's Static Area
On stack (during function call)
On Heap (when you allocate using new/malloc)
Global variables are always stored in static area. But to store a local variable in static area, you need the keyword static. As a static variable is not allocated on stack, you can access the variable on subsequent calls.
Also static keyword at global scope gives a variable internal linkage.Consequently the variable cannot be accessed from some other file using the extern qualifier.
You are correct, this is called "static linkage": The symbol declared as static is only available in the compilation unit where it is defined.
The other use of static would be inside a function:
void f() {
static int counter = 0;
counter++;
// ...
}
In this case the variable is only initialized once and keeps it's value through different calls of that function, like it would be a global variable. In this example the counter variable counts the number of times the function was called.
internal linkage vs external linkage by example
//file1.c
#include <stdio.h>
int glb_var=3;//global variable
int func(); //prototype of function
int main()
{
func();
func();
func();
return 0;
}
int func()
{
static int counter=0;//static varible
printf("val of counter=%d",counter);
counter+=5;
return 0;
}
when we will compile this program and run this program then os will load this program in memory.then below things will happened:
glb_var identifier will be stored in initialized data segment.
counter identifier will be stored in uninitialized data segment called ".bss".
static variable initialized once and the values persists during function calls.because static variable is stored in data segment not in stack so static variable persist during function calls.
So output of the program will be:
0 5 10
one important thing about static variable is that it has internal linkage.so we can access this variable to a particular file.In which they are defined (not in other file).
We can access global variable glb_var in other file by using extern keyword.
for eg:
//file2.c
#include <stdio.h>
extern glb_var; //for declaration of this variable
int main()
{
if(glb_var)
{
printf("glb_var=%d",glb_var);
}
}
output: 3
this is called external linkage.