I'm a little Confused about this code result:
#include <stdio.h>
int g;
void afunc(int x)
{
g = x; /* this sets the global to whatever x is */
}
int main(void)
{
int g = 10; /* Local g is now 10 */
afunc(20); /* but this function will set it to 20 */
printf("%d\n", g); /* so this will print "20" */
return 0;
}
Why the result is 10 Not 20 ?
The local variable g shadows the global g.
If you want the printf() to show 20, you have to shadow your local variable g with a declaration of the global one you want to print:
int main(void)
{
int g = 10; /* Local g is now 10 */
afunc(20); /* Set global g to 20 */
printf("%d\n", g); /* Print local g, "10" */
{
extern int g; /* Use global g */
printf("%d\n", g); /* Print global g, "20" */
}
return 0;
}
Calling afunc changes the global g, and main retains its local g.
Entering a function doesn’t swap its scope with the global scope. Each function* has its own scope.
* Among other things
If you get rid of the int in
int g = 10;
then main will also be referring to the same global variable as afunc is.
This is called variable shadowing
Have NOT modified your code, but have adjusted your comments to indicate what the code is doing. By the way, commenting your code is a really good idea and makes for better lab scores!! signed, A Former Graduate TA
#include <stdio.h>
int g; /* define a global variable
void afunc(int x)
{
g = x; /* this sets the global to whatever x is */
}
int main(void)
{
int g = 10; /* Define and set a Local g to 10 */
afunc(20); /* This function sets global x to 20 */
printf("%d\n", g); /* this prints local g "10" */
return 0;
}
To think about this "look-up" from main to global storage. You see local g before global g, thus local g is used.
In both the occasions, though the variable name appears to be same, they 2 are referring 2 different memory area. The variable g declared outside any function got stored in the RAM memory area, and the variable g declared inside main is got stored in stack area. So the invocation of afunc() is changing the variable g stored in RAM but again printing the variable g(stored in stack) which got declared locally.
Related
This question already has answers here:
About Tentative definition
(2 answers)
Closed 2 years ago.
So I have been trying to learn C on my own. So just a couple of videos and articles and a a book by my side. Although it sounds like a simple concept (I'm sure it is), I dnt think the concept is clear to me.
Can you please quote an example when a variable is declared or defined?(together and separately)
Like in some articles or forums I read they say
Int x; ( x is declared)
Somewhere it's written
Int x; ( x is defined).
When will the memory be allocated to the variable?
Again somewhere it is said that variable has to be defined first to get memory allocated and somewhere it's said it is allocated when a variable is declared?
Like in some articles or forums I read they say
Int x; ( x is declared)
Somewhere it's written
Int x; ( x is defined).
Actually the int x; declares and defines it at the same time so both are valid but incomplete.
The declaration shows the compiler the type of variable without creating it.
extern int x; // <- this is declaration
Definition creates the the object, if the object was declared before its definition must match the declaration.
extern int x;
int x;
Is valid but
extern int x;
double x;
is not.
I hope this give you a small overview about when variables become declared, allocated, initialized, deallocated and vanished (destroyed).
/* global variable A declared and memory for int is allocated */
/* memory will only be unallocated at global program exit */
/* global variable A initialized/defined with value 10 */
int A = 10;
void test(int D){
/* function test is called by main with argument test(5) */
/* local variable D is declared, memory for int is allocated */
/* and initialized with value 5 */
/* add local variable D to global variable A */
A = A + D;
/* after this point, local variable D will be deallocated */
/* and will vanish */
}
int main(int argc, char *argv[]){
/* local variable B declared, memory for int allocated */
/* and initialized with value 20 */
int B = 20;
{
/* local scoped variable C declared, memory for int allocated */
/* and initialized with value 30 */
int C = 30;
/* after this point, local scoped variable C will be */
/* deallocated and will vanish */
}
/* 5 is a local scoped const of size int, memory will be allocated */
test(5);
/* after this point, local scoped const 5 will be deallocated */
/* and will vanish */
/* after this point, local variable B will be deallocated */
/* and will vanish */
return A;
}
below is my code:
//main.c
int x = 9;
int f()
{
static int x = 0;
x += 1;
return x;
}
int main()
{
printf("Value is %d", f());
return 0;
}
my questions are:
Q1-inside f(), there is a local static varaible x defined, and there is gloabal variable also called x, the program does compile, but isn't it a conflict to the compiler and linker?
Q2-when I run it, the output is 1, which means that the x in x += 1; is the local static varaible x, not the gloabal variable x.But I could have mean "increment the global variable x", how can I do it?
A program can have the same name for local and global variables but the value of a local variable inside a function will take preference. There is no provision in C language to explicitly modify global variable with the same name as local inside local scope. In C++ though for accessing the global variable with same name, you'll have to use the scope resolution operator
#include <iostream>
using namespace std;
// Global variable declaration:
int g = 20;
int f()
{
int g = 0;
::g += 5;
return g;
}
int main () {
// Local variable declaration:
int g = 10;
cout << f(); // Local
cout << ::g; // Global
return 0;
}
Produces
0
25
Edit -
There is indeed a way to explicitly change the global scope variable inside local scope having same variable name ( only if global variable is not declared static )
int x = 9;
int f()
{
static int x = 0;
{
extern int x;
x += 1;
}
return x;
}
int main()
{
printf("Value is %d", f());
return 0;
}
Produces 0
Q1-inside f(), there is a local static varaible x defined, and there is gloabal variable also called x, isn't it a conflict to the compiler and linker?
No, the function always treats the local variable name first. The local name x in function f shadows the global name x.
Q2-when I run it, the output is 1, which means that the x in x += 1; is the local static varaible x, not the gloabal variable x.But I could have mean "increment the global variable x", how can I do it?
It's the same as your first question. You call f() which uses the local variable name x, which shadows the global name x. If you want the global x, you need to use it directly, not via function f.
Once conceptually, program control reaches the local declaration of x in f, the global x is shadowed. No syntax exists in C for accessing the global x.
Other than renaming one of the variables,
int f()
{
int* y = &x; // still refers to the global x
static int x = 0;
x += 1;
*y += 1; // increments the global x via the pointer
return x;
}
is an option, although not particularly sensible.
Q1. The language was intentionally designed this way so that we don't have to worry about what identifiers that reside in the global namespace - there can be quite a lot of them in large projects.
Internally the compiler doesn't use variable names at all, but sometimes their names must preserved for the purpose of generating debugger files (like ELF etc). In such situations, the compiler uses something called "name mangling" to keep the two variables separate internally. For example if I disassemble your code with gcc x86 and no optimizations, it names the local one x.0 internally, where the .0 thing is a compiler-specific addition, not to be confused with valid C syntax.
Q2. From inside the function f where the local x is visible, you can't. Unless you explicitly pass along a pointer to the other variable through a parameter etc. Again, we wouldn't want to change file scope variable values by accident.
Q1 -inside f(), there is a local static variable x defined, and there is global variable also called x, the program does compile, but isn't it a conflict to the compiler and linker?
No, it is not a conflict. What is going on here is the proce variable shadowing. The local x shadows the global x.
Q2 - when I run it, the output is 1, which means that the x in x += 1; is the local static variable x, not the global variable x. But I could have mean "increment the global variable x", how can I do it?
Declare the global variable new with extern inside an inner scope and return from that scope:
int f (void)
{
static int x = 0;
{
extern x;
x += 1;
return x;
}
}
Note that this won't work if the global x would be declared as static without adding code at the global space.
Here's an example regarding local and global variables. The result of this program displays the value of the global variable g.
What if I want to print/use the value of the global variable?
#include <stdio.h>
/* global variable declaration */
int g = 20;
int main ()
{
/* local variable declaration */
int g = 10;
printf("value of g = %d\n", g);
return 0;
}
Use a pointer to the global variable
#include <stdio.h>
/* global variable declaration */
int g = 20;
int main ()
{
int *pg = &g;
/* local variable declaration */
int g = 10;
printf("value of g = %d\n", *pg);
return 0;
}
This is not possible, the local g shadows the global one. However, in practice this is more a feature than a limitation since it means you don't have to worry about choosing variable names distinct from globals, and, of course, you can easily control your local names to allow access to a like-named global.
The scope of the variable int g=10; is just within main() so you can print the global variable anywhere apart from main() like calling some API as shown below.Else if you want to print it within main() then you need to have a pointer to your global variable and dereference it to get the value. The below approach doesn't introduce any new variable .
#include <stdio.h>
/* global variable declaration */
int g = 20;
void print_global()
{
printf("value of g = %d\n", g);
}
int main ()
{
/* local variable declaration */
int g = 10;
printf("value of g = %d\n", g);
print_global();
return 0;
}
Only for globals, you can just call another function to access it (and maybe return a pointer).
For all cases of shadowing, you can use a pointer you saved earlier.
Still, the best option is the simplest one: Just change the identifier in the inner scope to avoid shadowing.
Delete the local variable and declare it as global... Since the global variable has scope throughout the program, you can use it in any function of the program. But if you still want to declare the same variable locally then the local variable dominates the variable declared globally.
Suppose we have something along these lines
int f(int n);
....
do{
int a = b;
int b = f(a);
}
Is there any risk to saying
do{
int b = f(b);
}
instead, assuming a is not used elsewhere? Would it be stylistically preferable to do the former?
It is important to understand that you're not "altering" any variables here, just changing the meaning of a name.
The important concept is called the point of declaration.
Let's look at your example:
int b = 42;
{
int a = b;
int b = 23 * a;
printf("%d\n", b);
}
printf("%d\n", b);
or
int b = 42;
{
int b = 23 * b;
printf("%d\n", b);
}
printf("%d\n", b);
The name b references two objects, depending on where you are in the code, let's call them b1 and b2. This is unsurprising in case 1:
int b1 = 42;
{
int a = b1;
int b2 = 23 * a;
printf("%d\n", b2);
}
printf("%d\n", b1);
Since in C the point of declaration is before the initializer, the second example resolves differently:
int b1 = 42;
{
int b2 = 23 * b2;
printf("%d\n", b2);
}
printf("%d\n", b1);
Note that here there's no link between b1 and b2, you're initializing b2 with its own (undefined) value. A diligent compiler will warn you about this, like
x.c:7:13: warning: 'b' is used uninitialized in this function [-Wuninitialized]
As the compiler parses C code it populates a symbol table, this table contains information about all the different symbols and by symbols I mean identifiers, such as the names you give your variables, functions, and so forth ...
Most C programs are constructed out of nested scopes, global -> function -> component_statements and so on, each scope usually has its own symbol table, so the compiler uses a stack of symbol tables to keep track of everything, when a variable is looked up but isn't defined in the current symbol table it starts the search by going upward the stack until it hits global or usually last table ... but as soon one is defined in the current scope an entry is made 'shadowing' the previous.
heres a simple program to illustrate.
#include <stdio.h>
/* global accessable by most things ... */
int a = 5;
int main()
{ /* function scope */
int a = 4; /* shadowing global */
{ /* nested scope within function scope */
int b = a;
int a = b; /* shadowing function */
printf("%i\n", a);
}
return 0;
}
if you run this you would get 4 which is to be expected but anyone following your code would have to keep in the back of their mind that a is different from all the other a from global, function main ... If the programmer maintaining the code isn't aware of this things or you yourself forgot then you can have subtle run-time bugs that can be quite hard to debug ...
also note that if you run this:
#include <stdio.h>
/* global accessable by most things ... */
int a = 5;
int main()
{ /* function scope */
int a = 4; /* shadowing global */
{ /* nested scope within function scope */
int a = a; /* shadowing function, but not actually accessing outer scope */
printf("%i\n", a);
}
return 0;
}
you wouldn't get 4 but some large random int on my machine its 1606422610 since the variable is being assigned to itself that was just shadow, and c doesn't initialize variables.
How can I access a shadowed global variable in C? In C++ I can use :: for the global namespace.
If your file-scope variable is not static, then you can use a declaration that uses extern in a nested scope:
int c;
int main() {
{
int c = 0;
// now, c shadows ::c. just re-declare ::c in a
// nested scope:
{
extern int c;
c = 1;
}
// outputs 0
printf("%d\n", c);
}
// outputs 1
printf("%d\n", c);
return 0;
}
If the variable is declared with static, i don't see a way to refer to it.
There is no :: in c but you can use a getter function
#include <stdio.h>
int L=3;
inline int getL()
{
return L;
}
int main();
{
int L = 5;
printf("%d, %d", L, getL());
}
If you are talking about shadowed global var, then (on Linux) you can use dlsym() to find an address of the global variable, like this:
int myvar = 5; // global
{
int myvar = 6; // local var shadows global
int *pglob_myvar = (int *)dlsym(RTLD_NEXT, "myvar");
printf("Local: %d, global: %d\n", myvar, *pglob_myvar);
}
If you want your code to look sexy, use macro:
#define GLOBAL_ADDR(a,b) b =(typeof(b))dlsym(RTLD_NEXT, #a)
...
int *pglob_myvar;
GLOBAL_ADDR(myvar, pglob_myvar);
...
Depending on what you call shielded global variable in C, different answers are possible.
If you mean a global variable defined in another source file or a linked library, you only have to declare it again with the extern prefix:
extern int aGlobalDefinedElsewhere;
If you mean a global variable shadowed (or eclipsed, choose the terminology you prefer) by a local variable of the same name), there is no builtin way to do this in C. So you have either not to do it or to work around it. Possible solutions are:
getter/setter functions for accessing global variable (which is a good practice, in particular in multithreaded situations)
aliases to globals by way of a pointer defined before the local variable:
int noName;
{
int * aliasToNoName = &noName; /* reference to global */
int noName; /* declaration of local */
*aliasToNoName = noName; /* assign local to global */
}
what is a "shielded global variable" in pure C?
in C you have local variables, file local/global variables (static) and global variables (extern)
so file1.c:
int bla;
file2.c
extern int bla;
Yet another option is to reference the global before defining your local, or at least get a pointer to it first so you can access it after defining your local.
#include <stdio.h>
int x = 1234;
int main()
{
printf("%d\n",x); // prints global
int x = 456;
printf("%d\n",x); // prints local
}