I am learning storage classes in C.I have a simple code
enter code here
int f1()
{
static int i=0;
i++;
printf("%d",i);
}
int f2()
{
printf("%d",i);
}
int main()
{
f1();f2();f1();f2();
}
Compiler gives error as 'i' is undeclared in f2().
As I thought,memory static variables are allocated in data section of program memory.So any function in that file should be able to access it.
How does compiler knows that variable locally declared in function is bounded to that function only?How compiler evaluates that?
Although the lifetime of static variable isn't tied to the scope where it is defined (unlike variables with automatic storage duration):
{
static int i=0;
i++;
...
{
i++; // <-- still well defined, even in nested scope
}
}
i++; // <-- undefined
it is accessible only within this scope. The compiler just checks whether the symbol i has been defined before and it sees, that i has not been defined within that scope (the static int i=0; defines a variable that is accessible locally ~ compiler doesn't care about its lifetime).
In case you need it to be accessible out of its scope, you'll have to pass it out of it by reference (its address) or make it global:
static int i = 0;
...
{
i++;
}
...
i++; // <-- accessing global variable
static variables are indeed stored in the data section but are only in the scope of the function they are declared in.
You should do the following
static int i=0;
int f1()
{
i++;
printf("%d",i);
}
int f2()
{
printf("%d",i);
}
now the variable i can be accessed by both functions.
Always remember that the Scope is compile time not run-time. C has a flat memory structure. This means you can access anything from anywhere. You can make a pointer of i and can access it. But, C says undefined behaviour when the scope of the variable is over. This is a compiler restriction completely. You can also see the link - Is scope in C related only to compile time, as we know we can access any memory at run time? for more details. Also, this could be helpful A static variable and a global variable both reside in data segment. Still, static variable has scope limited. Why?. So, it is the translation unit that throws you the error.
Let's understand this by example.
#include "stdio.h"
int *ptr_i;
void func1()
{
static int i = 0;
ptr_i = &i;
i++;
printf("The static i=%d\r\n",i);
}
int main(int argc, char *argv[])
{
func1();
(*ptr_i)++;
func1();
}
The output of this program is the following.
The static i=1
The static i=3
As you could have understood, scope is not a run time. I was able to access the memory location used by i via pointer. Thus, you can access any memory in C as it is a flat memory structure. In this example, I accessed the memory of i using pointer to i. Note, Compiler never throw any error. Thus, scope is compile time not run time.
Related
I had this assignment at school, wherein I had to find the output of the following C code, and also, to explain the output.
#include<stdio.h>
int i;
void fun1(void);
void fun2(void);
int main()
{
fun1();
fun2();
return 0;
}
void fun1(){
i=20;
printf("%d\t",i);
}
void fun2(){
int i=50;
printf("%d",i);
}
The output is 20 50
Because in fun1() the Global Variable 'i' is assigned to 20 and printed. And in fun2() the variable 'i' is a Local Variable, which is declared and initialized to 50, which is then printed.
I have this following question out of curiosity, how do I use the global variable 'i', in fun2()?
A simple solution would be to simply change the name and avoid the whole thing. But my curiosity is due to Java, where there is a keyword "this" to access class variable instead of a local variable.
so is there any way to do that in C?
The only way is to hide the declaration of the local variable in a code block.
For example
#include <stdio.h>
int i = 10;
void fun2( void )
{
int i = 20;
printf("local i = %d\n",i);
{
extern int i;
printf( "global i = %d\n",i);
}
}
int main(void)
{
fun2();
}
The program output is
local i = 20
global i = 10
There is no way to access a global parameter inside a function that has a local variable with the same name. It is usually bad practice to create such local variables in C though, as you saw, it is not prohibited.
In C++ you can solve it using namespaces but there is no equivalent in C.
The best way is to pass parameters to the function
void fun2(int fromExternalWorld){
int i=50;
printf("%d ",fromExternalWorld);
printf("%d\n",i);
}
int main(void)
{
fun2(i);
}
Otherwise is not possible to have two symbols with same name visible in the same scope.
You could cheat and create a pointer to the global i before declaring the local i:
void fun2( void )
{
int *ip = &i; // get address of global i
int i = 50; // local i ”shadows" global i
printf( "local i = %d, global i = %d\n", i, *ip );
}
EDIT
Seeing as this answer got accepted, I must emphasize that you should never write code like this. This is a band-aid around poor programming practice.
Avoid globals where possible, and where not possible use a naming convention that clearly marks them as global and is unlikely to be shadowed (such as prefixing with a g_ or something similar).
I can't tell you how many hours I've wasted chasing down issues that were due to a naming collision like this.
I read that : static variable is initialised only once (unlike auto variable) and further definition of static variable would be bypassed during runtime. from the link.
then why I am getting error that "i was not declare " in the code given below.
I wrote program such that the static variable "i" initialized only first time when c is equal to 0 after that c increases.
I just want to know how the static variable really works and that's why i am declare static variable only once. My question is if static variable only declare once in each function call then why my code is not running and if it is necessary to declare it in each calling then why it does not initialise in each function call.
#include<stdio.h>
int c=0;
int test()
{
if(c==0)
{
static int i=0;
}
c++;
i++;
if(i==5)
printf("%d\n",i);
else
test();
}
int main()
{
test();
return 0;
}
You define the variable inside the local scope of if. It has no scope outside. static only deals with the extent (aka lifetime).
Use curly braces and indention. Then you will see your mistake.
Because the scope of i is just the if block in following code:
if(c==0)
static int i=0;
same as
if(c==0)
{
static int i=0;
}
i is not available outside the if block
If you put static variable inside of block or function then that variable will not longer available out of scope because without a curly brace {} only first statement after the if is executed. So it cannot be used anywhere else and compiler gives an error.
To fix your compilation error, declare I outside the condition. And set it to zero inside the condition -
static int i;
if ( c == 0 )
i = 0;
This will make the error go away.
But what you are trying to achieve doesn't require you to have a global variable c.
You can simply do
static int i = 0;
i++;
The first time it will be set to zero, hence forth it will not be initialized.
Its because , scope of variable 'i' is only inside (if) . So when you are incrementing 'i' , Compiler will throw error.
Adding the braces that others have mentioned will not fix the problem. The real solution is to just remove the if (c == 0) line completely. The static declaration of i should be the first line of the function.
What you want is this:
int test()
{
static int i=1;
if(i==5)
printf("%d\n",i);
else
test();
}
Automatic Storage used in a function does not re-initialize the i variable declared using the auto keyword.
Practice.c : main() and func() are in the Practice.c
#include <stdio.h>
main()
{
func();
func();
func();
}
func()
{
auto int i=1;
printf(" i = %d",i);
i=i+1;
}
After compilation when I execute Practice.exe the output is as follows :
i = 1
i = 1
i = 1
Every time main() calls func() i is re-initialized to 1. This is correct as scope of i is within the func() block, and when the control comes out of this block the value of i is lost. So, when I will be calling this func() function for the second time the value of i will be re-initialized to 1.
Check the following New.c Program.
New.c : contains both main() & func()
#include <stdio.h>
main()
{
func();
func();
func();
func();
func();
func();
func();
func();
}
func()
{
auto int i;
printf(" i = %d",i);
i=i+1;
}
Just to be sure, I called the function func() 8 times.
But in New.c, i is not initialized. When I executed this program after compilation, the output of it is as follows :
i = 4201582
i = 4201583
i = 4201584
i = 4201585
i = 4201586
i = 4201587
i = 4201588
i = 4201589
The output shows increment on every call. What is the exact reason behind this ?
The output shows increment on every call. What is the exact reason
behind this ?
Variables with automatic storage allocation are not initialized by default and it is undefined behaviour to access an uninitialized variable. This means the behaviour of your second program cannot be reasoned out.
Also, note that the default stororage class of variables in function scope is automatic. Therefore, you don't need the auto keyword to qualify the definition of i.
// in function scope
auto int i;
// equivalent to
int i;
Also, it's wrong to say
So, when I will be calling this func() function for the second time
the value of i will be re-initialized to 1.
The variable i is not re-initialized. It goes out of scope once the function containing it returns. When the function is called again, it's again allocated on the stack. This does not mean that it is allocated on the same memory address.
Also, you need to take care of the return type and parameter list of the functions. The implicit return type is int and empty parameter list means no information is available about the number and type of arguments which means the function takes a fixed but unknown number of arguments of unknown type. You should always explicitly mention void in the parameter list to mean that the function takes no argument.
#include <stdio.h>
// prototype of the function func
void func(void);
// main should have one of the below signatures -
// int main(void); or
// int main(int argc, char *argv[]);
int main(void)
{
func();
func();
func();
}
// explicitly mention void in the
// parameter list to mean the function
// takes no argument
void func(void)
{
// using auto keyword is redundant because
// local variables have automatic storage allocation
int i = 1;
printf("i = %d", i);
i = i + 1;
}
In the second case, you make use of i without ever having initialized it.
The value is therefore undefined by the language. The fact that you see a pattern of the value incrementing is an artifact of the particular compiler you are using.
In the first iteration, you have a random-seeming value that happens to be at the memory location that i represents. Your function increments the value at that memory location, then that memory location happens to be used for subsequent calls.
I was looking for a function to do some audio effect, and I found one written in C.
Inside this function, some variables are declared as Static. I am confused, I thought Static means these variables are not visibles to other files. But since they are declared inside inside a function, they are already not visible to other files.
What am I missing ?
static inside a function means that it will hold its value the next time the function is called.
For example,
int foo() {
static int i = 0;
printf("%d\n", i);
i++;
}
int main() {
foo(); // Prints 0
foo(); // Prints 1
}
I have some doubt on below code
#include<stdio.h>
int i=6;
int main()
{
int i=4;
{
extern int i;
printf("%d",i); //prints 6
}
printf("%d",i); //prints 4
}
we know that extern keyword says compiler, the variable is somewhere outside. So the question is why the extern keyword is accessing the global i variable but not the i variable which is within the main function? I was thinking there must be a contradiction because both variables are available to the inner braces as global variable. So does extern keyword access the variable which is outside the function or does it also access the variable which is outside the braces.
extern doesn't mean outside the current scope, it means an object with external linkage. An automatic variable never has external linkage, so your declaration extern int i can't possibly refer to that. Hence it's hiding it, the same as the automatic variable hid the global.
Before the printf that prints 6 you are asking the compiler to use the i defined after the #include. The closing brace then tells the compiler that the extern is no longer in effect, therefore it uses the scope where i is set to 4.
int i=4 is not global variable, if you try to access var i which is inside main in another function your compiler will thrown error about var i is undeclared. This code illustrates it.
void func() {
printf("i is %d\n",i);
}
main() {
int i=10;
func();
}
Whereas the i outside of main is global variable, which you can access in all functions.
I think you're asking whether you're right in thinking that the extern int i declaration should cause the first printf to resolve i to 4 because that int i=4 statement is in a parent scope of the scope in which the extern is declared.
The answer is no, hence the behaviour you're seeing. An extern declaration within a function is used to declare the existence of an external variable and won't ever resolve to a local variable (a variable declared within the function).
/* what Ed Heal said */
Yet, I think it would be best to illustrate it with additional example. I modified Your example to do a little more. The comments in the code tells the most of it:
#include <stdio.h>
int i = 6;
int main(void)
{
int i = 4;
printf("%d\n", i); /* prints 4 */
{
extern int i; /* this i is now "current". */
printf("%d\n", i); /* prints 6 */
{
int *x = &i; /* Save the address of the "old" i,
* before making a new one. */
int i = 32; /* one more i. Becomes the "current" i.*/
printf("%d\n", i); /* prints 32 */
printf("%d\n", *x); /* prints 6 - "old" i through a pointer.*/
}
/* The "previous" i goes out of scope.
* That extern one is "current" again. */
printf("%d\n", i); /* prints 6 again */
}
/* That extern i goes out of scope.
* The only remaining i is now "current". */
printf("%d\n", i); /* prints 4 again */
return 0;
}