Understanding extern storage specifier in C - c

I was going through Dennis Ritchie's book, The C programming language. In it, he says:
In certain circumstances, the extern declaration can be omitted. If the definition of the
external variable occurs in the source file before its use in a particular function, then there is no
need for an extern declaration in the function.
I tried quick code as follows:
#include "stdio.h"
int n = 0;
int nn = 111;
int main(int argc, char **argv) {
int n = 1;
printf("n from main(): %d\n", n);
function1();
function2();
}
void function1()
{
extern int n;
int nn; //declaring without extern keyword, this should point to global nn as per Dennis, but that does not seem to happen
int nnn; //declaring without extern keyword
printf("n from function1(): %d\n", n);
printf("nn from function1(): %d\n", nn);
printf("nnn from function1(): %d\n", nnn);
n = 10;
}
void function2()
{
extern int n;
int nn; //declaring without extern keyword, this should point to global nn as per Dennis, but that does not seem to happen
int nnn; //declaring without extern keyword
printf("n from function2(): %d\n", n);
printf("nn from function2(): %d\n", nn);
printf("nnn from function2(): %d\n", nnn);
}
int nnn = 222 ;
Below is sample output:
n from main(): 1
n from function1(): 0
nn from function1(): 1955388784
nnn from function1(): 6422476
n from function2(): 10
nn from function2(): 1955388784
nnn from function2(): 6422476
Notice what both functions function1() and function2() printed above. I guess, as per Dennis' statement, both should have referred global nn and should have printed 111. But that did not happen.
(You can try running code here)
Is it because the version about which Dennis is talking differs from the one using?
Am on MinGW.org GCC-8.2.0-5.

, then there is no need for an extern declaration in the function.
Here what Dennis Ritchie saying is that, If definition of nn varibale is already occured in source file then now in function1() and funcation2() you do not need to declare variable as extern again, like (extern int nn;) you can directly use them.
But by doing int nn; in your funcation1() you are defining one another local variable. Which is complete different variable.

The keyword extern is used with objects to reference objects that have file scope.
This declaration in your functions
int nn; //declaring without extern keyword, this should point to global nn as per Dennis, but that does not seem to happen
has a block scope. So it is a definition of a local variable.. It does not have linkage.
The quote you provided means that if there is a definition of a file scope variable then it has external or internal linkage. So there is no need to use the keyword extern
For example
//…
int n = 10; // definition of a variable with external linkage
void f()
{
printf( "n = %d\n", n );
}
//...

You're completely misunderstanding Mr. Richie. He's saying that this:
int n;
void foo()
{
n = 42;
}
requires no extern because the referenced variable n is defined before the function, foo, that uses it.
Were the code like this:
void foo()
{
n = 42;
}
int n;
the compiler now has no idea what you're talking about when using n in the body of foo. There is no n until later, but the compiler has no idea that there ever will be.
You can address this by:
extern int n;
void foo()
{
n = 42;
}
int n;
Now, when compiling foo, the compiler knows there is some int called n ... somewhere. Doesn't know where yet, and frankly doesn't care. Likewise, this will also work:
void foo()
{
extern int n;
n = 42;
}
int n;
That's all he's trying to say. Your code and comments seem to think that by doing this:
void foo()
{
int n;
n = 42;
}
int n;
the n in foo will magically resolve to the outer n. That isn't how the language works. All this does is make the code compile because now the compiler sees an n that fulfills usage for n = 42. It's an automatic variable (lifetime to the { scope } in which it is declared). It has absolutely nothing to do with the int n; outside that scope (but can easily shadow (hide) the name n if you're not careful. That is exactly what is happening in your code.

You seem to be misinterpreting the last part of the statement that "there is no need for an extern declaration in the function" to mean "there is no need for an extern keyword in the function."
What Dennis is saying is that extern int n; in your functions is equivalent to not declaring n at all. extern int n; is not equivalent to int n;, e.g. in main.

I just wanted to know whether it should print 111 as per the author. Now I realized, author is saying "...before its use..." and by "use", he meant "use without (re)definition inside function".
If we define variable again inside function without extern, it will create local variable for function.
(Dont know if I should answer my own question, may be others will correct me if am wrong in this understanding again.)

Related

How to access local and global variable with same name in C

I had this assignment at school, wherein I had to find the output of the following C code, and also, to explain the output.
#include<stdio.h>
int i;
void fun1(void);
void fun2(void);
int main()
{
fun1();
fun2();
return 0;
}
void fun1(){
i=20;
printf("%d\t",i);
}
void fun2(){
int i=50;
printf("%d",i);
}
The output is 20 50
Because in fun1() the Global Variable 'i' is assigned to 20 and printed. And in fun2() the variable 'i' is a Local Variable, which is declared and initialized to 50, which is then printed.
I have this following question out of curiosity, how do I use the global variable 'i', in fun2()?
A simple solution would be to simply change the name and avoid the whole thing. But my curiosity is due to Java, where there is a keyword "this" to access class variable instead of a local variable.
so is there any way to do that in C?
The only way is to hide the declaration of the local variable in a code block.
For example
#include <stdio.h>
int i = 10;
void fun2( void )
{
int i = 20;
printf("local i = %d\n",i);
{
extern int i;
printf( "global i = %d\n",i);
}
}
int main(void)
{
fun2();
}
The program output is
local i = 20
global i = 10
There is no way to access a global parameter inside a function that has a local variable with the same name. It is usually bad practice to create such local variables in C though, as you saw, it is not prohibited.
In C++ you can solve it using namespaces but there is no equivalent in C.
The best way is to pass parameters to the function
void fun2(int fromExternalWorld){
int i=50;
printf("%d ",fromExternalWorld);
printf("%d\n",i);
}
int main(void)
{
fun2(i);
}
Otherwise is not possible to have two symbols with same name visible in the same scope.
You could cheat and create a pointer to the global i before declaring the local i:
void fun2( void )
{
int *ip = &i; // get address of global i
int i = 50; // local i ”shadows" global i
printf( "local i = %d, global i = %d\n", i, *ip );
}
EDIT
Seeing as this answer got accepted, I must emphasize that you should never write code like this. This is a band-aid around poor programming practice.
Avoid globals where possible, and where not possible use a naming convention that clearly marks them as global and is unlikely to be shadowed (such as prefixing with a g_ or something similar).
I can't tell you how many hours I've wasted chasing down issues that were due to a naming collision like this.

Is variable declaration necessary in C?

See the comments to see what is being referred as declaration.
If the whole variable declaration part was missing, what would be the problem?
Appears that variable definition and initialization either simultaneously or separately like in the example would suffice.
#include <stdio.h>
// Variable declaration:
extern int a, b;
extern int c;
extern float f;
int main () {
/* variable definition: */
int a, b;
int c;
float f;
/* actual initialization */
a = 10;
b = 20;
c = a + b;
printf("value of c : %d \n", c);
f = 70.0/3.0;
printf("value of f : %f \n", f);
return 0;
}
If the declaration was missing then it would create no problem in main function since the locally defined variables i.e. a,b,c,f will be used in the functionality of main till its scope ends.
The declaration merely tells that the definition lies elsewhere (in some other .c file) or the definition lies after the function main in the same .c file.
There will be no problem here if the mentioned declaration is missing.
// Variable declaration:
extern int a, b;
extern int c;
extern float f;
This tells the compiler that these variables are defined somewhere else(in another file).
/* variable definition: */
int a, b;
int c;
float f;
This is where you define variables but they are not the same as the external variables you declared since they are in the inner scope of the main function.
The scope is the place where variables live. extern keyword notes that the scope is global.
You can define variables with the same name in an inner scope and access only them as you did in the main function but it's not a good practice.
void foo()
{
int a = 5;
printf("%d\n", a); // 5
// Creating an inner scope
{
int a = 20;
printf("%d\n", a); // 20
}
printf("%d\n", a); // 5
}
The correct way to use the extern keyword with variables is like this.
//h1.h
extern int global_var; // Declaration of the variable
//c1.c
#include h1.h
int global_var = 0; // Definition of the global var. Memory is allocated here.
//main.c
#include h1.h
int main()
{
printf("global var value is %d\n", global_var); // use of the var defined and
// initialized in c1.c
return 0;
}
This program will print 0 since the variable is defined and initialized in c1.c.
Extern extends the visibility of the C variables and C functions. so that lets the compiler know that there is another place that those vars are declared and memory was allocated for them elsewhere.
for example in another c file.
if you compile a c file containing a global var for example:
int c = 5;
and you create a function on you c file that uses this c var, for example:
int someFunc(void){
return c;}
if you run someFunc in your main and print its return value, you will get 5. but you must compile both c files together.
in your program, you only use the locally allocated var declared in your main function.
When it comes to simple variables, there is really no difference between the declaration and definition. There is a difference when it comes to structs and functions. Here is an example:
// Declarations
struct myStruct;
int foo();
int main()
{
...
}
// Definitions
struct myStruct {
int a, b;
};
int foo() {
return 42;
}
In your case, you are hiding the previous declarations so that they are not accessible before the end of the scope. This is commonly called shadowing. It's basically the same thing as this:
int main()
{
int i=0;
printf("i: %d\n", i);
{
int i=42; // Now the previous i is inaccessible within this scope
printf("i: %d\n", i);
}
// And now it is accessible again
printf("i: %d\n", i);
}

Is there a scope resolution operator in C language?

I am reading a book on the C language ('Mastering C'), and found the topic on scope resolution operator (::) on page 203, on Google Books here.
But when I run the following code sample (copied from the book), the C compiler gives me an error. I searched on the internet but I am unable to find any reference to a scope resolution operator in C.
#include <stdio.h>
int a = 50;
int main(void)
{
int a =10;
printf("%d",a);
printf("%d\n", ::a);
return 0;
}
So if I want to access a global variable then how could I do that from within the main() function ?
No. C does not have a scope resolution operator. C++ has one (::). Perhaps you are (or your book is) confusing C with C++.
You asked how you could access the global variable a from within a function (here main) which has its own local variable a. You can't do this in C. It is lexically out of scope. Of course you could take the address of the variable somewhere else and pass that in as a pointer, but that's a different thing entirely. Just rename the variable, i.e. 'don't do that'
No, namespaces are a feature of C++.
It is, however, possible to refer to global a in your example.
You can achieve this by using the extern keyword:
#include <stdio.h>
int a = 50;
int main(void)
{
int a = 10;
printf("%d\n",a);
{ // Note the scope
extern int a; // Uses the global now
printf("%d\n", a);
}
return 0;
}
That's a bit tricky, though. It's bad style. Don't do that.
:: operator is available in C++ not C. If you wanted to access the global variable, use
#include <stdio.h>
int a = 50;
int main(void)
{
int a =10;
printf("%d",a); //prints 10
{
extern int a;
printf("%d", a); //prints 50
}
return 0;
}
Or you could use a pointer which holds the address of the global variable a and then dereference the pointer if you want to print the value of the global variable a.
No (the :: operator is C++ specific). In C, if you use the same identifier in different overlapping scopes (say, file scope a and block scope a), the block scope identifier shadows the file scope identifier and there is no way to refer to the shadowed identifier.
It is generally best programming practice to avoid shadowed variables. Many lint type programs can warn about this situation.
In plain C, there is no scope resolution. You have to name your variables differently.
That means that all variables a below are different ones:
#include <stdio.h>
int a = 50;
int main(void)
{
int a = 10;
{
int a = 20;
int i;
for (i = 0; i < 10; i++) {
int a = 30;
}
}
return 0;
}
You may use pointers to access and edit global variables in C.
#include <stdio.h>
#include <stdlib.h>
int a;
a=78;
int *ptr=&a; //pointer for global a
int main()
{
int a=0;
printf("%d",a); //Prints 0 as local variable
printf("%d",*ptr);
ptr=30; //changes the value of global variable through pointer
printf("%d",*ptr); //Now it prints 30
return 0;
}
It entirely depends on what kind of compiler you're using to execute your code.
#include <stdio.h>
int a = 50;
int main(void)
{
int a =10;
printf("%d\n",a);
printf("%d\n", ::a);
return 0;
}
Try running this code in Turbo C compiler, and you will get the results.
Now, regarding the C book that you're following, the examples codes present in the book must be in terms with Turbo C/C++ compiler and not the gcc compiler.

how to use extern in C?

I have this code:
#include <stdio.h>
extern int x;
void a() {
int x = 100;
printf("%d ",x );
x += 5;
}
void b() {
static int x = -10;
printf("%d ", x);
x += 5;
}
void c(){
printf("%d ", x);
x += 2;
}
int main() {
int x = 10;
a();
b();
c();
a();
b();
c();
printf("%d ", x);
getchar();
return 0;
}
int x = 0;
I was sure that the fact that extern in declared here, I will have a compilation error - but everything passed.
also , what is the meaning of extern when it's inside the C file itself? shouldn't it be in another file?
Is there a way to declare this variable in order for this not to compile?
The extern keyword declares a variable, and tells the compiler there is a definition for it elsewhere. In the case of the posted code, the definition of x occurs after main(). If you remove the int x = 0; after main() the code will not build (it will compile but will fail to link due to undefined symbol x).
extern is commonly used to declare variables (or functions) in header files and have the definition in a separate source (.c) file to make the same variable available to multiple translation units (and avoid multiple definition errors):
/* my.h */
#ifndef MY_HEADER
#define MY_HEADER
extern int x;
#endif
/* my.c */
#include "my.h"
int x = 0;
Note that the declaration of x in functions a(), b() and main() hide the global variable x.
You have a declaration for an identifier at file scope, so if no other declaration for the identifier would've been existing at file scope, the identifier would have had and external linkage. But, you've defined the identifier at file scope at the last line, in the pasted code.
So,extern int x;
refers to the globally defined: int x = 0; at the bottom of your file. :)
If you run this code you should get x's value as 2 and subsequently 4 because the externed x variable refers to the int x=0 after the main().
Extern is used for declaration a variable in a compilation unit, this variable was defined in other compilation unit.
What is the difference between a definition and a declaration?
For functions it is optional.
Read: http://en.wikipedia.org/wiki/External_variable
In your piece of code, each of the three function uses another 'i'. Only c() uses the global x.

extern and global in c

Can anyone please tell me is there any special requirement to use either EXTERN or GLOBAL variables in a C program?
I do not see any difference in a program like below, if I change from gloabl to extern.
#include <stdio.h>
#include <stdlib.h>
int myGlobalvar = 10;
int main(int argc, char *argv[])
{
int myFunc(int);
int i;
i = 12;
myGlobalvar = 100;
printf("Value of myGlobalvar is %d , i = %d\n", myGlobalvar, i);
i = myFunc(10);
printf("Value of passed value : %d\n",i);
printf("again Value of myGlobalvar is %d , i = %d\n", myGlobalvar, i);
system("PAUSE");
return 0;
}
int myFunc(int i)
{
i = 20 + 1000;
//extern int myGlobalvar;
myGlobalvar = 20000;
// printf("Value of passed value : %d",i);
return i;
}
If uncomment extern int myGlobalvar, the value does not change.
Is there any correct difference between both?
Can anyone please correct me?
The keyword extern means "the storage for this variable is allocated elsewhere". It tells the compiler "I'm referencing myGlobalvar here, and you haven't seen it before, but that's OK; the linker will know what you are talking about." In your specific example it's not particularly useful, because the compiler does know about myGlobalvar -- it's defined earlier in the same translation unit (.c or .cc file.) You normally use extern when you want to refer to something that is not in the current translation unit, such as a variable that's defined in a library you will be linking to.
(Of course, normally that library would declare the extern variables for you, in a header file that you should include.)
From Here:
A global variable in C/C++ is a variable which can be accessed from any module in your program.
int myGlobalVariable;
This allocates storage for the data, and tells the compiler that you want to access that storage with the name 'myGlobalVariable'.
But what do you do if you want to access that variable from another module in the program? You can't use the same statement given above, because then you'll have 2 variables named 'myGlobalVariable', and that's not allowed. So, the solution is to let your other modules DECLARE the variable without DEFINING it:
extern int myGlobalVariable;
This tells the compiler "there's a variable defined in another module called myGlobalVariable, of type integer. I want you to accept my attempts to access it, but don't allocate storage for it because another module has already done that".
Since myGlobalvar has been defined before the function myFunc. Its declaration inside the function is redundant.
But if the definition was after the function, we must have the declaration.
int myFunc(int i)
{
i = 20 + 1000;
extern int myGlobalvar; // Declaration must now.
myGlobalvar = 20000;
printf("Value of passed value : %d",i);
return i;
}
int myGlobalvar = 10; // Def after the function.
In short: GLOBAL variables are declared in one file. But they can be accessed in another file only with the EXTERN word before (in this another file). In the same file, no need of EXTERN.
for example:
my_file.cpp
int global_var = 3;
int main(){
}
You can access the global variable in the same file. No need to use EXTERN:
my_file.cpp
int global_var = 3;
int main(){
++global_var;
std::cout << global_var; // Displays '4'
}
Global variable, by definition, can also be accessed by all the other files.
BUT, in this case, you need to access the global variable using EXTERN.
So, with my_file.cpp declaring the global_var, in other_file.cpp if you try this:
other_file.cpp
int main(){
++global_var; // ERROR!!! Compiler is complaining of a 'non-declared' variable
std::cout << global_var;
}
Instead, do:
int main(){
extern int global_var;//Note: 'int global_var' without 'extern' would
// simply create a separate different variable
++global_var; // and '++global_var' wouldn't work since it'll
// complain that the variable was not initiazed.
std::cout << global_var; // WORKING: it shows '4'
}
myGlobalVar as you've defined it is a global variable, visible from all the places in your program. There's no need declaring it extern in the same .c file . That is useful for other .c files to let the compiler know this variable is going to be used.

Resources