C static scope variable undefined - c

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;

Related

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

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.

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.

Global Array Issues Not Updating, C Programming

I have a program distributed across a number of files. There are a number of functions which need access to a global array. The issue I'm having is that I don't know the size of the array before the program starts. It opens up a file and then downloads a number of points, and then the array is created with a corresponding size. But for the array to be global, it needs to be declared outside of the main function i.e. before I know the number of points.
What I've tried to do right now is:
file1.c:
#include <stdio.h>
#include "file3.h"
int useful[];
int main()
{
int useful[10];
int i;
for (i = 0; i < 10; i++) {
useful[i] = i+1;
}
SPN();
return 0;
}
file2.c:
#include <stdio.h>
#include "file3.h"
void SPN() {
int i;
for (i = 0; i < 10; i++) {
printf("%i\n", useful[i]);
}
}
file3.h:
extern int useful[];
extern void SPN();
What I'm getting in output is just a bunch of 0s. At first I was thinking that the second int useful[... in file1.c creates a new array with a different internal name, but that doesn't seem to make any sense considering that no segmentation fault is triggered by SPN() when it tries to access memory outside the arrays bounds (if useful[] creates an array and isn't changed, it has default size 1 i.e. < 10). Help?
The int useful[10]; isn't initializing the global int useful[]; or anything like that. It's a new variable, and with the loop here
for (i = 0; i < 10; i++) {
useful[i] = i+1;
}
You're modifying the second useful without touching the global one. This is then discarded at the end of the function.
Instead have a global variable like this:
int *useful;
And initialize it this way:
useful = malloc(sizeof(int)*10);
The declaration of useful inside the main is shadowing the external one.
This means that the values that you think are inserting (in the main) in the global variable are actually going into the local variable.
Take a look at the following article about shadowing for more info.
It might also be interesting to look at scope rules in C.

Initialization for static variables

static int i = 5;
static int j = i;
int main()
{
return 0;
}
I am initializing the static variable by another static variable which is declared before that but also I am getting variable. Please tell me why this is error.
You cannot initialize j with i, because at compile time, compiler will not know the value of i.To assign the value j = i, the code need to be executed at run time. When initialize the global or static in C, the compiler and linker need to work together to create the layout of memory. Compiler will give the value and linker need to give the address of the variable.
The below code will work:
static int i = 5;
static int j;
int main()
{
j=i;
return 0;
}
If this is a real case, you maybe should initialize them explicit.

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