Why is the static storage behaving differently in the two examples? - c

So here is an example:
#include <stdio.h>
int main(void) {
static int i=0;
printf("%d",i);
static int i=0;
printf("%d",i);
return 0;
}
This gives me an error:
error: redefinition of 'i'
Now here is another Example :
#include <stdio.h>
void increment(void) {
static unsigned int counter = 0;
counter++;
printf("%d ", counter);
}
int main(void) {
for (int i = 0; i < 5; i++) {
increment();
}
return 0;
}
This gives the output :
1 2 3 4 5
Why does this happen ?
In the second example by calling the function aren't we redeclaring it? And shouldn't the output be 1 1 1 1 1 ?

In the second example by calling the function aren't we redeclaring it?
No, we aren't: We are declaring i in a different scope; specifically, in the body of a different function. You can only define a variable once within a given scope (ignoring sub-scopes); but you can define a variable of the same name in different scopes:
int i; // global scope
void foo()
{
int i; // scope - body of foo
{
int i; // a sub-scope of the body of foo
}
}
int main()
{
int i; // a different scope - body of main, not body of foo
}
and the "closest" definition to a command is the one which will be relevant; it will "shadow" the other variables of the same name which might otherwise be usable in that scope.
Of course, it's not a good idea to define many variables with the same name which may shadow each other - it's confusing and their names will likely not be meaningful. People often use a one-letter variable for a loop counter: i, j, k etc. - but then you would tend avoid using i for something more long-lasting.
1 2 3 4 5...
Why does this happen ?
Because within the increment() function, the counter is a static unsigned int, meaning it has static storage duration - it is only initialized once, and maintains its value between invocations of the function.

Related

C static variables initialization

I learned some C and came across an explanation for static variables.
They showed this code:
#include<stdio.h>
int fun()
{
static int count = 0;
count++;
return count;
}
int main()
{
printf("%d ", fun());
printf("%d ", fun());
return 0;
}
I can't understand why calling the function twice is fine, because the line
static int count = 0;
actually runs twice...
I can't understand how is that possible...
Can you actually declare it twice or does the compiler just ignore it the second time?
This (statics/globals) is where an initializing definition is really different from an uninitialized definition followed by an assignment.
Historically, the former even used to have different syntax (int count /*no '=' here*/ 0;).
When you do:
int fun() {
static int count = 0;
//...
}
then except for the different scopes (but not lifetimes) of count, it's equivalent to:
static int count = 0; //wider scope, same lifetime
int fun() {
//...
}
In both cases, the static variable becomes initialized at load time, typically en-masse with other statics and globals in the executable.
static variables are initialized on program startup, not every time the function is called.
... because the line static int count = 0; actually runs twice.
No. Just once, right before main() is called.

C static scope variable undefined

My goal is to add (without modifying any of the existing code) a function retrieve() which returns the current value of the counter.
#include <stdio.h>
void increment(void){
static unsigned int counter = 0;
counter++;
printf("%d\n", counter);
}
int main(void){
for (int i = 0; i < 5; i++){
increment();
}
printf("counter = %d\n", retrieve());
return 0;
}
However, everything I try is running into a scope issue. Namely that counter has not yet been instantiated yet so the compiler considers it to be an undefined name. I've tried adding a function
int retrieve(void){
return counter;
}
between increment and main and also within both increment and main themselves. My understanding of the static keyword is that once the variable is instantiated it will persist beyond the block it is defined in for the length of the program execution. So I think the issue I'm running into is that the variable is not yet instantiated. Any help would be great.
Scope and lifetime are two different things, and they're partly independent.
Scope is the region of program text in which an identifier is visible.
Lifetime (or storage duration) is the duration during program execution in which an object exists.
The object named counter, because it's defined with static, has static storage duration, which means that it exists during the entire execution of the program. But the identifier counter has block scope, which means that the name is visible only from its declaration to the } that terminates the innermost block in which it's declared. (In this case, that block happens to be the outermost block of a function definition.)
you need to move counter into global scope
#include <stdio.h>
static unsigned int counter = 0; <<<=========
void increment(void){
counter++;
printf("%d\n", counter);
}
int retrieve(void){
return counter;
}
int main(void){
for (int i = 0; i < 5; i++){
increment();
}
printf("counter = %d\n", retrieve());
return 0;
}
accepted best practice is to indicate in the name that its global
unsigned int COUNTER = 0;
or
unsigned int g_counter = 0;

Simple if statement in C always return true

I dont have time to explain it deeply, its very simple code but the function always return 'y'(=true)
It is expected to write each number from 1 to squareroot of the generated random number and decide whether it is dividable or not but when i run it, somehow the if statement in the function always return true
#include <stdio.h>
#include <stdlib.h>
int a,b,i;
char c;
char abcd(char c);
int main()
{
srand(time(NULL));
int a=rand()%512;
b=sqrt(a);
i=1;
do{
if(abcd(c)=='y')printf("number %d is dividable by %d\n",a,i);
else printf("number %d is not dividable by %d\n",a,i);
i++;
}while(i<=b);
return 0;
}
char abcd(char c)
{
if(a%i==0)return'y';
else return 'n';
}
When you declare int a inside main as
int a=rand()%512;
you are shadowing your global variable a. The a in main is a different variable that has scope only local to the function main. Therefore, when you are using the value a inside char abcd(char c), this value is the global variable a which is default initialized to 0.
Also, why are you passing a char c variable to function abcd. You aren't using it. Please consider renaming your functions to something that more clearly describes their intent.
You have two different variables a:
one declared at file scope
int a,b,i;
and one declared in main():
int a=rand()%512;
Within its scope (almost all of main()), the latter shadows the former. Elsewhere, such as in function abcd(), only the former is visible. The former is default initialized to 0 and no other value is ever assigned to it, so no matter what value i takes, inside abcd(), the expression a%i evaluates to 0.
This is a good lesson in avoiding file-scope variables. Functions should operate on data accessed directly or indirectly through their parameters, or obtained from an external source. It is poor form for functions to exchange data through file-scope variables. Moreover, it was a red flag to me that your function abcd() declares a parameter that it never uses. Suggested variation:
char abcd(int dividend, int divisor) {
return (dividend % divisor) ? 'n' : 'y';
}
Or even better (because better name and more appropriate return type):
_Bool is_divisible(int dividend, int divisor) {
return !(dividend % divisor);
}
The reason yours doesn't work is because the variable a was declared in a separate scope from the abcd function. The a variable you use inside the abcd function is automatically set to 0, which is why it returns true every time (0 % anything is 0).
When you call abcd, you would need to pass a inside the parameters for it to use the correct value.
But really you don't need the abcd function, you can save a lot of code and directly check if it's divisible. This code should work:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
int a, b, i;
char c;
int main()
{
srand(time(NULL));
int a = rand() % 512;
b = sqrt(a);
i = 1;
do {
if (a%i == 0)printf("number %d is dividable by %d\n", a, i);
else printf("number %d is not dividable by %d\n", a, i);
i++;
} while (i <= b);
return 0;
}

Why is the output of the following two segments different?

#include <stdio.h>
int main()
{
static int i = 5; // here
if (--i){
printf("%d ", i);
main();
}
}
Output: 4 3 2 1
#include <stdio.h>
int main()
{
int i = 5; // here
if (--i){
printf("%d ", i);
main();
}
}
Output: 4 4 4 4... (Segmentation fault)
Any idea how static int variable is taken into account only once and int is taken over and over again?
When you declare a static variable in a function, the function "remembers" the last value of the variable even after it terminates.
void Foo() {
static int x = 5;
}
In the example above, you are telling the compiler that x shall be "remembered" and has an initial value of 5. Subsequent calls to Foo() does not reassign x a value of 5, but uses the previously remembered value.
In contrast:
void Bar() {
int x = 5;
}
Here, you are telling the compiler that everytime Bar() executes, a new variable x is to be created on the stack and assigned a value of 5.
A variable declared as static inside of a function retains its value each time the function is called. It is initialized only once, when the function is first called. So when the function calls itself the value of i is retained from the prior call.
A local variable that is not static is specific to a given call of a function, so each time the function is called a new copy of the variable is created and initialized. This results in i being 5 each time, which in turn results in infinite recursion leading to a stack overflow and a core dump.

Accessing the global variable when global and local variables have same name

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

Resources