Initialize static variable with the argument of a function - c

How can I do something like this?
void function(int n)
{
static int number = n;
.
.
.
}

If you want to initialize the static variable to n during the first invocation of the function, you can do it like this:
void function(int n)
{
static int initialized = 0;
static int number;
if (!initialized) {
number = n;
initialized = 1;
}
.
.
.
}
You can't initialize number to n directly since number is initialized at compile time, while n is known only at run time.

You cannot.
Quoting the C11 standard, chapter §6.7.9/P4
All the expressions in an initializer for an object that has static or thread storage duration
shall be constant expressions or string literals.
To elaborate, the objects with static storage duration are initialized only once, prior to the execution to the program. Thereby, it is not possible to use a run-time value to be used as the explicit initializer.
Related, from chapter §6.2.4
An object whose identifier is declared [...] 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.

Related

Does a static variable inside a function ever go out of scope?

While reading this Question I noticed an interesting scenario. The question has a function which is only called once:
int* missing_elements(int arr[], int len){
static int arr2[]={0};
for(int i=0,j=1; i < 7; i++,j++){
if(arr[i] != j){
arr2[i]=j;
if(arr[i] == j++){
break;
}
}
}
return arr2;
}
The function is returning a pointer to an array that is defined as static within the function. I'm curious about how the scope of arr2[] is handled. If arr2[] was defined as not static then then it would fall out of scope and you couldn't assume that the returned pointer would point to valid data.
My question is since arr2 is static will it always be in scope even if the function that defines it will never be called again. Is this undefined behavior or can we assume that it never loses scope?
My question is since arr2 is static will it always be in scope even if
the function that defines it will never be called again. Is this
undefined behavior or can we assume that it never loses scope?
If we look at draft N2310 - 6.2.4 Storage durations of objects
You'll see that it states (emphasis mine)
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.

Redeclaration of static variables in C... never happens?

I'm trying to fully understand how static variables work in C. I understand that using the static keyword makes the lifetime of the variable equal to the duration of the program. The following example has one thing that confuses me though...
My static_test.c file:
#include <stdio.h>
void foo(){
static int counter = 0;
counter++;
printf("This function has been called %i times.\n",counter);
return;
}
int main(){
int i;
for(i=0;i<10;i++){
foo();
}
return 0;
}
When I first read this example it makes me wonder why the function doesn't print out 0 every time since we are assigning 0 to the static variable.
Is this because once a static variable is declared the compiler ignores another declaration of the same variable on the next calls to my foo() function?
Thanks!
Despite the use of =, this is an initialization, NOT an assignment. So it happens when the variable is initialized and not when the 'statement' is apparently 'executed'. Since it is a static variable, it is initialized once when the program starts, rather than every time the function runs.
Static variables are initialized exactly once at program start, before your function is ever called. The fact that it's a local variable doesn't affect this rule.
In addition, static storage class variables are automatically initialized to zero if not explicitly initialized; the = 0 in your program is superfluous.
From the C11 drafts standard (ISO/IEC 9899:201x), section 6.2.4 Storage durations of objects, paragraph 3:
An object whose identifier is declared … 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.
Yes, the compiler looks for an initial assignment after declaring a static variable and only executes it once, when the program starts.
This only happens when you declare the variable though. For example,
void foo(){
static int counter;
counter = 0;
counter++;
printf("This function has been called %i times.\n",counter);
return;
}
Would print 1 every time.
Static means the variable exists outside of the life time of the function. Think of it as a slightly clever global variable.

Definition of global variables using a non constant initializer

#include <stdio.h>
int i=10;
int j=i;
int main()
{
printf("%d",j);
}
I get an error stating that initialization element is not a constant? What is the reason behind this?
What is the reason behind this?
C(unlike C++) does not allow initialization of global values with non constant values.
C99 Standard: Section 6.7.8:
All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.
You could try using:
int i=10;
int j=0;
int main()
{
j=i;//This should be the first statement in the main() and you achieve the same functionality as ur code
return 0;
}
The only true C way is to initialize it at runtime. Although in C++ your code will work fine, without any compilation errors.
The C standard clearly prohibits initialization of global objects with non-constant values. The Section 6.7.8 of the C99 standard says:
All the expressions in an initializer for an object that has static
storage duration shall be constant expressions or string literals.
The definition of an object with static storage duration is in section 6.2.4:
An object whose identifier is declared 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.
The idea behind this requirement is to have all static storage duration object initialized at compile time. The compiler prepares all static data in pre-initialized form so that it requires no additional initializing code at run time. I.e. when the compiled program is loaded, all such variables begin their lives in already initialized state.
In the first standardized version of C language (C89/90) this requirement also applied to aggregate initializers, even when they were used with local variables.
void foo(void)
{
int a = 5;
struct S { int x, y; } s = { a, a }; /* ERROR: initializer not constant */
}
Apparently the reason for that restriction was that the aggregate initializers were supposed to be built in advance in the pre-initialized data segment, just like global variables.
Use this:-
int i=10,j=1;
int main()
{
printf("%d",j);
}
Though it is a minor change but it will work

Why I can not initialize and int value to a static variable

I am getting ERROR when I am running this program at the line
static int b = a; //error : initializer element is not constant
Can not understand why?
#include <stdio.h>
// #include <setjmp.h>
int main()
{
int a = 5;
static int b = a;
return 0;
}
Apart from the other reasons stated in other answers here, please see the below statement in the Standard.
The C Standard says this in Point-4 (Section 6.7.8 Initialization):
All the expressions in an initializer for an object that has static storage duration
shall be constant expressions or string literals.
Additionally, as to what is a constant expression, it says in Section 6.6 Constant Expressions as below:
A constant expression can be evaluated during translation rather than runtime, and
accordingly may be used in any place that a constant may be.
In C (unlike C++), the initializer for any object with static storage duration - including function statics - must be constant expressions. In your example a is not a constant expression so the initialization is not valid.
C99 6.7.8 / 4:
All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.
Static variable is always global in the sense it is not on any thread's stack, and it is not important if its declaration is inside a function or not.
So the initialization of the global variable b is performed during program start-up, before any function (including main) gets called, i.e. no a exists at that time, because a is local variable which gets its memory place on stack after the function (here main) is called.
Hence you really cannot expect the compiler to accept it.
Following from Als's answer ...
// This is really crappy code but demonstrates the problem another way ....
#include <stdio.h>
int main(int argc, char *argv[])
{
static int b = argc ; // how can the compiler know
// what to assign at compile time?
return 0;
}

Why can't I initialize a static variable with a non literal value?

I had this code:
int foo(void){
return 1;
}
int main(void){
static const int x = foo();
//do stuff
return 0;
}
But I got an error about initializing a static variable with a non-const value. I thought it had something to do with the const specifier, but it didn't. I ended dropping the const keyword and doing this:
int foo(void){
return 1;
}
int main(void){
static int x = 0;
if (x == 0) x = foo();
//do stuff
return 0;
}
Now, why can't the compiler just delay the initialization of the static int x variable until it's used, and more importantly, why can't it just put it in a read-write section, and just enforce that it's not written to in compile time? I'd like to use the const AND static keyword for improved semantics in my code, but I don't really care how the compiler handles this, just let it work.
Is my understanding of the C standard wrong? Or is my compiler sucking? It's MSVC 9.0.
C requires it.
From the C Standard:
(C99, 6.7.8p4) "All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals."
Note that the const qualifier does not mean constant but rather read-only. A const object is not a constant in C.
The reason a static object cannot be initialized by a non constant value is related to the fact that the initialization of a static object is done "prior to program startup" (C99, 6.2.4p3).
The value for initialization must be determined at compile or link time. C doesn't have the concept of constructors that could be run at the startup of the program.
This constraint comes from C standard's section 6.7.8/4, so it's not just your compiler:
All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.
The reason for this is that unlike C++ standard, C sdoes not require execution environments to provide an entry point for pre-run initialization (while certainly not prohibiting it; The manner and timing of static initialization (5.1.2) is unspecified).

Resources