c variables scope - c

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.

Related

Extern declaration of variable with no link to a definition

#include <stdio.h>
extern int i;
int main()
{
int i = 5;
printf("%d", i);
return 0;
}
From what I understand, there is no global variable named i to which the external declaration of i should refer. So it should produce a linker error. Yet this code runs successfully and prints 5. Why so?
#include <stdio.h>
extern int i; // this is one variable called "i"
int main()
{
int i = 5; // it is second variable called "i"
printf("%d", i);
return 0;
}
You have variable i declared (but never defined) in the global (file) scope.
You also have variable i defined in the local scope of function main. The global scope i and the automatic function scope i variables are not related.
As you never use the global i it was optimized out by the compiler and the linker did not have to search for the object i in object and library files.
BTW your main function should be int main(void) not int main()
Because there is a local definition with init int i =5; within main().
The linker does not have a problem with i being accessed form inside a function which has a local definition for it.
The comments by Selvin, Refugnic Eternium and Barmar provide more insights.
The comment by M.M. helpfully quotes from standard. "Since you never use it..." might be confusing. You do use it, yes, but only in local scope with a definition, not outside that local scope. The experiment proposed by Baramar changes exactly this detail.

Is there efficiency lost when declaring an automatic variable in a frequently opening block scope { }?

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);

Why tentative definition concept in C not valid for local variables [duplicate]

When I compile the code below
#include<stdio.h>
int main()
{
int a;
int a = 10;
printf("a is %d \n",a);
return 0;
}
I get an error:
test3.c: In function ‘main’:
test3.c:6:5: error: redeclaration of ‘a’ with no linkage
test3.c:5:5: note: previous declaration of ‘a’ was here
But if I make the variable global then it works fine.
#include<stdio.h>
int a;
int a = 10;
int main()
{
printf("a is %d \n",a);
return 0;
}
Why is declaring the same global variable twice not an error, but doing that for a local variable is an error?
In C, the statement int a; when made at file scope, is a declaration and a tentative definition. You can have as many tentative definitions as you want, as long as they all match each other.
If a definition (with an initializer) appears before the end of the translation unit, the variable will be initialized to that value. Having multiple initialization values is a compiler error.
If the end of the translation unit is reached, and no non-tentative definition was found, the variable will be zero initialized.
The above does not apply for local variables. Here a declaration also serves as a definition, and having more than one leads to an error.
The other reason I could think of is that un-initialized global variables are stored in the BSS (Block Structured Segment) where are the global variables that are initialized are stored in Data Segment.
I am guessing that there is some kind of a name space resolution and when there is a conflict the variable in the Data segment overrides the one in the Block Structured Segment.
if you were to declare
int a =5
int a = 10
in the global scope (both in the data segment) there would be conflict as expected.
You can't have two global variables with the same name in C program.
C might allow multiple definitions in the same file scope through the tentative definition rule, but in any case all definitions will refer to the same variable.
Local Variable
In C, multiple local variables are not "merged" into one.
All the local variables with the same name will be referring to the different int-sized piece of memory.
#include<stdio.h>
int main()
{
int a;
int a = 10;
printf("a is %d \n",a);
return 0;
}
So when assigning the memory to the redeclaration of the same variable it gives an Error.
Global Variable
In C, multiple global variables are "merged" into one. So you have indeed just one global variable, declared multiple times. This goes back to a time when extern wasn't needed (or possibly didn't exist - not quite sure) in C.
In other words, all global variables with the same name will be converted to be one variable - so your
#include<stdio.h>
int a;
int a = 10;
int main()
{
printf("a is %d \n",a);
return 0;
}
will be referring to the same int-sized piece of memory.

Stack frame structure for a function with a sub scope

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.

Terminology definition - Scope in C application

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.

Resources