Suppose I have a function that declares and initializes two local variables – which by default have the storage duration auto. This function then calls a second function, to which it passes the addresses of these two local variables. Can this second function safely use these pointers?
A trivial programmatic example, to supplement that description:
#include <stdio.h>
int adder(int *a, int *b)
{
return *a + *b;
}
int main()
{
auto int a = 5; // `auto' is redundant; included for clarity
auto int b = 3;
// adder() gets the addresses of two auto variables! is this an issue?
int result = adder(&a, &b);
printf("5 + 3 = %d\n", result);
return 0;
}
This program works as expected, printing 5 + 3 = 8.
Usually, when I have questions about C, I turn to the standard, and this was no exception. Specifically, I checked ISO/IEC 9899, §6.2.4. It says there, in part:
4
An object whose identifier is declared with no linkage and without
the storage-class specifier static has automatic storage duration.
5
For such an object that does not have a variable length array type,
its lifetime extends from entry into the block with which it is
associated until execution of that block ends in any way. (Entering an
enclosed block or calling a function suspends, but does not end,
execution of the current block.) If the block is entered recursively,
a new instance of the object is created each time. The initial value
of the object is indeterminate. If an initialization is specified for
the object, it is performed each time the declaration is reached in
the execution of the block; otherwise, the value becomes indeterminate
each time the declaration is reached.
Reading this, I reason the following points:
Variables a and b have storage duration auto, which I've made explicit using the auto keyword.
Calling the adder() function corresponds to the parenthetical in clause 5, in the partial quote above. That is, entering the adder() function "suspends, but does not end," the execution of the current block (which is main()).
Since the main() block is not "end[ed] in any way," storage for a and b is guaranteed. Thus, accessing them using the addresses &a and &b, even inside adder(), should be safe.
My question, then, is: am I correct in this? Or am I just getting "lucky," and accessing memory locations that, by happenstance, have not been overwritten?
P.S. I was unable to find an exact answer to this question through either Google or SO's search. If you can, mark this as a duplicate and I'll delete it.
Yes, it is safe and basically your assumptions are correct. The lifetime of an automatic object is from the entry in the block where it has been declared until the block terminates.
(C99, 6.2.4p5) "For such an object [...] its lifetime extends from entry into the block with which it is associated until execution of that block ends in any way.
Your reasoning is correct for your particular function call chain, and you have read and quoted the relevant portions of the standard. This is a perfectly valid use of pointers to local variables.
Where you have to be wary is if the function stores the pointer values in a structure that has a lifetime longer than its own call. Consider two functions, foo(), and bar():
int *g_ptr;
void bar (int *p) {
g_ptr = p;
}
void foo () {
int x = 10;
bar(&x);
}
int main () {
foo ();
/* ...do something with g_ptr? */
return 0;
}
In this case, the variable xs lifetime ends with foo() returns. However, the pointer to x has been stored in g_ptr by bar(). In this case, it was an error for foo() to pass a pointer to its local variable x to bar().
What this means is that in order to know whether or not it is valid to pass a pointer to a local variable to a function, you have to know what that function will do with it.
Those variables are allocated in the stack. As long as you do not return from the function that declared them, they remain valid.
As I'm not yet allowed to comment, I'd rather write another answer as amendment to jxh's answer above:
Please see my elaborate answer here for a similar question. This contains a real world example where the aliasing in the called function makes your code break even though it follows all the c-language rules.
Even though it is legal in the C-language I consider it as harmful to pass pointers to automatic variables in a function call. You never know (and often you don't want to know) what exactly the called function does with the passed values. When the called function establishes an alias, you get in big trouble.
Related
In C an extern variable gets the initial value of "zero".
however after reading about this particular class category.It says that declearing variable as an extern, means the value only passed the "decleration stage".How come a variable can get an initial value without procceding to the initialization stage and allocating a memory for the particular variable?
Please consider the following code:
extern int var;
int main(void)
{
var = 10;
return 0;
}
I understand why a problemetic sitution arises: we tried to initialize a value to a variable which is not allocated in the memory(the variable doesn't really exist).
My point is: why it's memory doesn't exist and followoing "extern's" terminology the variable has an initial value of "zero". In my mind it means that the memory does actually exist if it has an itial value....
For this code to be valid, another part of the program must contain the definition of var, e.g.:
int var = 0;
which is where the initial value comes from. If you don't provide an initializer then it behaves as if you initialized with = {0} (that is the rule for static storage duration variables).
I'm getting this error while trying to define a local static variable.
Initializer element is not constant.
I want to retain the first value of var inside this recursion. How to pass this?
Hope you also clarify the side effects of assigning arguments to the local static variables to be prevented.
int function(int var)
{
static int index=var;
//some code ...
return var==0?1:function(var-1);
}
the static variable is initialized before the function even starts. It's like a global variable, only with function scope. The compiler cannot use a value that it doesn't know yet.
You could workaround this with an helper boolean:
int function(int var)
{
static int index_is_set=0;
static int index;
if (!index_is_set)
{
index = var;
index_is_set = 1;
}
//some code ...
return var==0?1:function(var-1);
}
so first time you enter the function it sets the value, sets the boolean flag to 1 so it's not overwritten by further calls.
note that this isn't very useful as a construct, since if you are to call your function recursively a second time in your program (after having obtained the result the first time, I mean), there's no way to reset the variable (unless you make index_is_set global so you can reset it from the outside).
Note that it is possible to get rid of all this static thing altogether by using the start value as an extra parameter.
int function(int var, int start_value)
{
// ...
return var==0 ? 1 : function(var-1,start_value);
}
First call goes like:
function(20,20);
or wrapped in a function which hides this implementation:
int function_wrapper(int var)
{
return function(var,var);
}
the start value is passed along all calls. Consumes a bit more auto variable space, but is much cleaner, no memory effect & easier to debug.
The case:
static int index=var;
Is a declaration with initializer (see ISO/IEC 9899:2011 §6.7 Declarations). The statement declares a static variable initialized to a value that must be a constant defined at compile time. In plain word because the value is initialized before the execution starts the initializer must be defined before function usage.
If you want retain the first value of a recursion the way you are using isn't a good choice for many reasons:
The value, as seen, cannot be assigned using a not constant value
If it worked, the next time you enter the function it would be reassigned clearing the very first value
A local static variable has unlimited life, but scope limited to the local function. Then you cannot access or initialize it from external scopes.
a solution can be to pass to the function 2 variables a first value and the value passing the same value the very first call of the function:
int function(int first_var, int var)
{
//some code ...
return var==0?1:function(first_var, var-1);
}
...
function(5, 5); //First call
For sake of completeness it could work by breaking your statement in a definition of the static variable without initialization (or with a generic initialization), followed by an assignment (ISO/IEC 9899:2011 §6.5.16 Assignment operators):
int function(int var)
{
static int index; //Declaration
index=var; //Assignement
//some code ...
return var==0?1:function(var-1);
}
But because it will be reassigned each time the function reenters, it is only a big nonsense...
An 80k reputation contributor R.. told me on SO that we can't initialize global variables with the return value of a function as that's not considered a constant,and global variables must be initialized with a constant.And true to his words,I get the following error for this program as expected-- initializer element is not a constant.Here is the program:
#include<stdio.h>
int foo();
int gvar=foo(); //ERROR
int main()
{
printf("%d",gvar);
}
int foo()
{
return 8;
}
But in this context,I just don't understand why the followed altered version of the above program shows no error at all and works fine.In this second program,I am initializing the same global variable with the return value of the same function foo().Can you tell me what is the rigorous technical reason for this variation in results?Why is initializing the global variable with the return value of a function at it's declaration causing error but the same initialization with the same return value works fine when done from within a function?
#include<stdio.h>
int foo();
int gvar;
int main()
{
gvar=foo();
printf("%d",gvar);
}
int foo()
{
return 8;
}
Output 8
The reason behind it is that in order to determine a value produced by a function one needs to execute code, and that there is no code execution done in C when initializing static and global variables.
Compiler and linker work together to prepare a byte image of the global memory segment: the compiler provides the values, and the linker performs their final layout. At runtime, the image of the segment is loaded in memory as is, without further modifications. This happens before any code gets executed, so no function calls can be made.
Note that this does not mean that it is not possible for some technical reason, only that C designers decided against doing it. For example, C++ compiler generates a code segment that calls constructors of global objects, which gets executed before the control is passed to main().
The second version doesn't have an initializer for gvar. gvar is declared and defined at global scope without an initializer. It has static storage duration, so it is initialized with zero.
The assignment in main is just that: an assignment, not an initialization.
In case 1, global variable is assigned with a variable while it is declared.
But in the second case, global variable is assigned(which is already declared) with return value of foo().
Forming of data section, text section all happens during compilation.
Global variables will be in data section(bss or initialized data section), so at compile time, foo() is not invoked right? and return value of foo() is not known during compilation.
But second case, when the text section get executed, gvar is assigned with return value of foo(). It is valid.
You can maybe think of it like this: when main() starts, all global variables must already have their initializer values. And they can't, as you've been told, get those by calling functions since main() is really where execution starts, in a C program.
we could not call any function from outer of the function.Not like shell script.function only allow to called from inside of function body.
In c first execution begins from main(), compiler don't know the function calling if that stands on outer of function it may taken as prototype if arg and return types provided.
we can putting return value of function by calling from main or others function block, to the variable,the function called then (that global) variable modified.
but we can use macro in global variable as needs.
as:
#define max() 12
int glob=max();
main()
{
}
I understand this:
int i = 3; // declaration with definition
It tells the compiler to:
Reserve space in memory to hold integer value.
Associate name with memory location.
Store the value 3 at this location.
But what does this declaration tell the compiler:
int i; // declaration
The declaration tells the compiler to reserve space for the variable i and associate the name i with that space (your points 1. and 2.).
If i is a global variable it is initialized to 0.
If it is local the value of i is undefined (probably garbage, ie. some random value) and you should assign to it before reading it.
There are two cases: at file scope (i.e. for a global declaration), and in a function.
In a function, the declaration int i; does two things: it declares a variable called i whose type is int, and it reserves some storage in memory to put a value of type int. What it does not do is give the variable a value. The storage used by i will still contain whatever garbage was there before. You need to initialize the variable, i.e. assign a value to it, before you can read a value from it. Good compilers will warn you if you don't initialize the variable.
At file scope, int i also declares a variable called i. The rest depends on other things: this is known as a tentative definition. You can have multiple such declarations in your file. At most one of these is allowed to have an initializer, making it a full-fleged definition. If none of the declarations of i at file scope have an initializer, the declaration is also a definition, and there is an implicit initialization to 0. Thus:
int i;
/* ... more code ...*/
int i;
is valid, and i will be initialized to 0 (assuming these are the only declarations of i at file scope). Whereas:
int i;
int i = 3;
is also valid, and i will be initialized to 3 when the program starts.
In practice, at file scope, there's often a difference between leaving the initialization implicit and explicitly initializing to 0. Many compilers will store an explicit 0 in the binary, but let the operating system initialize implicit zeroes automatically when the program is loaded. Don't worry about this unless you have a large global array (which shouldn't happen often) or you work on tiny embedded systems.
It says to reserve space for an integer called i. As far as what is in there is up to the compiler and is undefined.
It does the same thing as your previous declaration:
allocates space on the stack for the integer
the compiler associates a name with the space (your running program won't do this, necessarily)
the integer is not initialized.
Others have pretty much answered the question, but I will mention two points that (I think ) haven't been mentioned so far:
int i;
defines i to be an int, with garbage in it (unless i is "global"). Such garbage might be a trap representation, which means that using it could be "bad":
A trap representation is a set of bits which, when interpreted as a value of a specific type, causes undefined behavior. Trap representations are most commonly seen on floating point and pointer values, but in theory, almost any type could have trap representations. An uninitialized object might hold a trap representation. This gives the same behavior as the old rule: access to uninitialized objects produces undefined behavior.
Also, int i; could also be a tentative definition, which means that you're telling the compiler: "i is an int, and I will define it later. If I don't, then define it for me.". Here is a very good explanation of why C has tentative definitions.
There are three kinds of memory for objects:
1) external (often called "global" but that really refers to scope). Objects here are created before running the program; 2) stack (created during run time); 3) heap (eg malloced).
"int i;" either creates the object in the external memory or on the stack. If it's in a function, it's created on the stack (if "static" isn't also used.
Objects created in external memory are initialized to zero if they are not explicitly initialized (e.g, "int i = 3";
You can create an external object in a function by using the "static" keyword.
int a; // external memory with "global" scope. Initialized to 0 implicitly.
static int b; // external memory with file (module) scope. Initialized to 0 implicitly.
int c = 3; // external memory initialized to 3.
f()
{
int d; // created on the stack. Goes away when the block exits. Filled with random trash because there is no initialization.
int e = 4; // stack object initialized to 3.
static int f; // "f" is external but not global. Like all externals, it's implicitly initialized to zero.
static int g = 3; // An external like f but initialized to 3.
}
What will be printed out? 6 6 or 6 7? And why?
void foo()
{
static int x = 5;
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
There are two issues here, lifetime and scope.
The scope of variable is where the variable name can be seen. Here, x is visible only inside function foo().
The lifetime of a variable is the period over which it exists. If x were defined without the keyword static, the lifetime would be from the entry into foo() to the return from foo(); so it would be re-initialized to 5 on every call.
The keyword static acts to extend the lifetime of a variable to the lifetime of the programme; e.g. initialization occurs once and once only and then the variable retains its value - whatever it has come to be - over all future calls to foo().
Output: 6 7
Reason: static variable is initialised only once (unlike auto variable) and further definition of static variable would be bypassed during runtime. And if it is not initialised manually, it is initialised by value 0 automatically.
So,
void foo() {
static int x = 5; // assigns value of 5 only once
x++;
printf("%d", x);
}
int main() {
foo(); // x = 6
foo(); // x = 7
return 0;
}
That is the same as having the following program:
static int x = 5;
void foo()
{
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
All that the static keyword does in that program is it tells the compiler (essentially) 'hey, I have a variable here that I don't want anyone else accessing, don't tell anyone else it exists'.
Inside a method, the static keyword tells the compiler the same as above, but also, 'don't tell anyone that this exists outside of this function, it should only be accessible inside this function'.
I hope this helps
6 7
compiler arranges that static variable initialization does not happen each time the function is entered
Output: 6,7
Reason
The declaration of x is inside foo but the x=5 initialization takes place outside of foo!
What we need to understand here is that
static int x = 5;
is not the same as
static int x;
x = 5;
Other answers have used the important words here, scope and lifetime, and pointed out that the scope of x is from the point of its declaration in the function foo to the end of the function foo. For example I checked by moving the declaration to the end of the function, and that makes x undeclared at the x++; statement.
So the static int x (scope) part of the statement actually applies where you read it, somewhere INSIDE the function and only from there onwards, not above it inside the function.
However the x = 5 (lifetime) part of the statement is initialization of the variable and happening OUTSIDE of the function as part of the program loading. Variable x is born with a value of 5 when the program loads.
I read this in one of the comments: "Also, this doesn't address the really confusing part, which is the fact that the initializer is skipped on subsequent calls." It is skipped on all calls. Initialization of the variable is outside of the function code proper.
The value of 5 is theoretically set regardless of whether or not foo is called at all, although a compiler might optimize the function away if you don't call it anywhere. The value of 5 should be in the variable before foo is ever called.
Inside of foo, the statement static int x = 5; is unlikely to be generating any code at all.
I found the address x uses when I put a function foo into a program of mine, and then (correctly) guessed that the same location would be used if I ran the program again. The partial screen capture below shows that x has the value 5 even before the first call to foo.
A static variable inside a function has a lifespan as long as your program runs. It won't be allocated every time your function is called and deallocated when your function returns.
Let's just read the Wikipedia article on Static Variables...
Static local variables: variables declared as static inside a function are statically allocated while having the same scope as automatic local variables. Hence whatever values the function puts into its static local variables during one call will still be present when the function is called again.
Vadiklk,
Why ...? Reason is that static variable is initialized only once, and maintains its value throughout the program.
means, you can use static variable between function calls.
also it can be used to count "how many times a function is called"
main()
{
static int var = 5;
printf("%d ",var--);
if(var)
main();
}
and answer is 5 4 3 2 1 and not 5 5 5 5 5 5 .... (infinite loop) as you are expecting.
again, reason is static variable is initialized once, when next time main() is called
it will not be initialize to 5 because it is already initialized in the program.So we can change the value but can not reinitialized. Thats how static variable works.
or you can consider as per storage: static variables are stored on Data Section of a program and variables which are stored in Data Section are initialized once. and before initialization they are kept in BSS section.
In turn Auto(local) variables are stored on Stack and all the variables on stack reinitialized all time when function is called as new FAR(function activation record) is created for that.
okay for more understanding, do the above example without "static" and let you know what will be the output. That make you to understand the difference between these two.
Thanks
Javed
The output will be 6 7. A static variable (whether inside a function or not) is initialized exactly once, before any function in that translation unit executes. After that, it retains its value until modified.
You will get 6 7 printed as, as is easily tested, and here's the reason: When foo is first called, the static variable x is initialized to 5. Then it is incremented to 6 and printed.
Now for the next call to foo. The program skips the static variable initialization, and instead uses the value 6 which was assigned to x the last time around. The execution proceeds as normal, giving you the value 7.
6 7
x is a global variable that is visible only from foo(). 5 is its initial value, as stored in the .data section of the code. Any subsequent modification overwrite previous value. There is no assignment code generated in the function body.
6 and 7
Because static variable intialise only once,
So 5++ becomes 6 at 1st call
6++ becomes 7 at 2nd call
Note-when 2nd call occurs it takes x value is 6 instead of 5 because x is static variable.
In C++11 at least, when the expression used to initialize a local static variable is not a 'constexpr' (cannot be evaluated by the compiler), then initialization must happen during the first call to the function. The simplest example is to directly use a parameter to intialize the local static variable. Thus the compiler must emit code to guess whether the call is the first one or not, which in turn requires a local boolean variable. I've compiled such example and checked this is true by seeing the assembly code. The example can be like this:
void f( int p )
{
static const int first_p = p ;
cout << "first p == " << p << endl ;
}
void main()
{
f(1); f(2); f(3);
}
of course, when the expresion is 'constexpr', then this is not required and the variable can be initialized on program load by using a value stored by the compiler in the output assembly code.
Share what I learned about this point.
In C static is a declaration specifier, which falls into three categories:
storage classes: there are four classes: auto, static, extern and register.
type qualifiers: like keywords: const, volatile, etc.
type specifiers: like keywords: void, char, short, int, etc.
So static is a storage classes. It will determine the following three properties of each variable in a C program.
storage duration: means when memory is allocated for the variable and when the memory is released. A variable with static storage duration stays at the same memory location as long as the program is running.
scope: means the portion of the program text in which the variable can be accessed.
linkage: means the extent to which the variable can be shared by different parts(or files) of a program.
The static storage class has a different effect on a variable depending on it is declared outside a block or inside a block. Let's focus on the case when a static variable declared within a block(the one discussed in this post).
A static variable in a block is initialized only once.
If a function is called multiple times, the static block variable is shared by all calls of the function.
This understanding is based on the book "c programming a modern approach"