C scope and extern usage - c

I have this source of a single file that is successfully compiled in C:
#include <stdio.h>
int a;
unsigned char b = 'A';
extern int alpha;
int main() {
extern unsigned char b;
double a = 3.4;
{
extern a;
printf("%d %d\n", b, a+1);
}
return 0;
}
After running it, the output is
65 1
Could anybody please tell me why the extern a statement will capture the global value instead of the double local one and why the printf statement print the global value instead of the local one?
Also, I have noticed that if I change the statement on line 3 from
int a;
to
int a2;
I will get an error from the extern a; statement. Why does not a just use the assignment double a=3.4; ? It's not like it is bound to be int.

It's not like it is bound to be int.
Actually, it is. In the declaration
extern a;
The (implicit) type of a is indeed int. Declarations in C without any specific type always default to int.
In addition, an extern declaration cannot refer to a local variable (even one declared within the same function).

The line
extern a;
shadows the previous declaration. Until the scope where this is declared ends, this declaration takes precedence over the definition
double a = 3.4;

Related

Cannot print called float variables

I cannot print float variables when calling my functions. int variables print but floats won't print their proper value when passed to my function.
I tried to change the float to int and that worked
int main() {
int foo = 6;
call(foo);
}
void call(int bar) {
printf("%d", bar);
}
This worked and it does indeed print 6.
But, doing the same but with floats only prints out 0.00000:
int main() {
float foo = 6;
call(foo);
}
void call(float bar) {
printf("%f", bar);
}
How do I correctly call and then print float variables?
you need a forward declaration of call
void call(float integerrrr);
int main(){
float integerrrr=6;
call(integerrrr);
}
void call(float integerrrr){
printf("%f", integerrrr);
}
your compiler probably warned you about this
You could simply define call above main instead of below it. The compiler must have seen the declaration of functions when they are used, so a forward declaration like pm100 suggests is one way. Moving the whole definition above main is the another (that does not require a forward declaration).
#include <stdio.h>
void call(float integerrrr){
printf("%f", integerrrr);
}
int main(void){
float integerrrr = 6;
call(integerrrr); // now the compiler knows about this function
}
INT type variables i can print but float just does not
If your program actually compiles as-is it will use an old (obsolete) rule that makes an implicit declaration of undeclared functions when they are used. The implicit declaration would be int call(); - which does not match your actual function. The program (even the one that seems to be working) therefore had undefined behavior.
the compiler of c work from top to bottom so line by line,
so u will have to call the first function void call() then your main function:
void call(float integerrrr){
printf("%f", integerrrr);
}
int main(){
float integerrrr=6;
call(integerrrr);
}

How to properly define external variables?

In the program
case0.c
int main()
{
int x;
x = 4;
}
x is first declared as an int, and memory is allocated for x on the following line. No problems here.
However, if I write the files (as part of a bigger program)
case1.c
extern int x;
x = 4;
I get, from gcc, warning: data definition has no type or storage class. Similarly, if I do
case2.c
extern int x = 4;
gcc also doesn't like it and gives warning: 'x' initialized and declared 'extern'
The only case that doesn't throw any warnings is
case3.c
extern int x;
int x = 4;
Why does case 1 give an error, when case 0 doesn't? Is case 3 the one and only way I should define external variables?
x is first declared as an int, and memory is allocated for x on the following line. No problems here.
No, that is not what happens. Inside a function, int x; defines x, which reserves memory for it. Then x = 4; stores a value in that memory.
extern int x;
x = 4;
extern int x; declares there to be an x but does not define it. If the program uses this x, it should define it somewhere else.
Outside a function, only declarations should appear. However, x = 4; is a statement, so it is not proper outside a function.
extern int x = 4;
This is valid C, but it is unconventional usage, so the compiler warns you. Conventionally, we write int x = 4; to define and initialize x, and we write extern int x; to declare x without defining it.
extern int x = 4; is defined by the standard; in this context, it is effectively the same as int x = 4;. But programmers generally do not use that form.
(If there is a visible prior declaration of x, such as static int x;, then extern int x = 4; does differ from int x = 4;. extern int x = 4; will refer to the x of the prior declaration, whereas int x = 4; will attempt to create a new x.)
extern int x;
int x = 4;
extern int x; declares x but does not define it.
int x = 4; defines x and initializes it.
Is case 3 the one and only way I should define external variables?
If you only need to use x in one translation unit, you can use int x = 4; by itself, without extern int x;. If you need to use x in multiple translation units, you should put extern int x; in a header file and include that header file in each source file that uses x, including the one that defines it.
"Is case 3 the one and only way I should define external variables?"
No, not if it is to be visible and usable by other source files in the project. If it is only to be used in the file in which it is created, there is no reason to give it extern duration.
The scenario requiring a variable with extern duration is when the value it stores is required to be referenced by multiple source files.
A common way (place) to create extern variables to support that scenario :
Declare variable with extern modifier in a header file.
Define the extern variable in a project file with visibility to its declaration. (eg, can be either a .h or .c . More commonly done in .c) If defined in a file other than the declaration file, file must #include the declaration file.
Use the extern variable in any source file by # including its declaration file
Example:
file.h
//anywhere in header file
extern int g_number;//declare extern variable.
//Note extern keywork required only during declaration
//Not during definition
//prototypes
void output_extern_variable( void );
void update_extern_variable( void );
...
file.c
//in file global space
#include "file.h"
int g_number = 25;//define extern variable
int main(void)
{
output_extern_variable();
update_extern_variable();
output_extern_variable();
...
file2.c
#include "file.h"
...
void output_extern_variable(void)
{
printf("Value of g_number is: %d\n", g_number);
}
void update_extern_variable( int *var )
(
g_number += 1;
)

Understanding extern storage specifier in 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.)

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

Global variable does not take new value

I was making a simple C program
#include<stdio.h>
static int a;
a = 5;
int main()
{
printf("%d",a);
return 0;
}
Compiler error: "non static declaration of 'a' follows static declaration"
What does this error mean?
what this error log means?
It is a little tricky: what looks like an assignment
a = 5;
is treated as
int a = 5;
due to an old C rule that allowed you to declare int variables and int-returning functions without specifying their type explicitly (this is definitely not a good idea in the modern version of C).
Note that this is treated as a declaration with an implicit int only in the scope outside a function body.
You can fix it by combining the declaration with initialization, like this:
static int a = 5;
Outside a function you can only declare variables, you cannot have actual code statements.
a = 5;
is being interpreted as another declaration, when your intent I think is to write some code.
instead declare and initialise a at the same time
static int a = 5;
Your first declaration of a is static (ahas internal linkage).
The second declaration is not static (a has external linkage). Yes, a = 5; is a declaration with implicit type int in this case.
Both do not agree.
Btw. for functions this would be o.k. because the second declaration would "inherit" the internal linkage.
We cannot write any assignment statement globally. For example:
#include <stdio.h>
static int i=10; //Initialization statement
i=25; //Assignment statement
int main(){
printf("%d",i);
return 0;
}
Output: Compilation error
Note: Assigning any value to the variable at the time of declaration is known as initialization while assigning any value to variable not at the time of declaration is known assignment.
You can't set value as you did it: a = 5; before main(...). See code below:
static int a = 1; //default = 0;
int main()
{
printf("a = %d\n", a);
a = 2;
printf("a = %d\n", a);
return 0;
}
Output:
a = 1
a = 2
A = 5 is considered as an attempt to create another variable called a. You should put the = 5 after static int a.
Static int a = 5;
Just a little modification to your code will help you to understand it.
#include<stdio.h>
//static int a; //comment this statement
a = 5;
int main()
{
printf("%d",a);
return 0;
}
now compile this code [please enable your compiler's warnings]
Then you will get a warning something like this
data definition has no type or storage class [enabled by default]
So now try to understand this warning it means that compiler treat statement a=5 as a definition but without data type. But compiler unable default data type that is int.
so this statement is equivalent to
int a=5;

Resources