When I compile the code below
#include<stdio.h>
int main()
{
int a;
int a = 10;
printf("a is %d \n",a);
return 0;
}
I get an error:
test3.c: In function ‘main’:
test3.c:6:5: error: redeclaration of ‘a’ with no linkage
test3.c:5:5: note: previous declaration of ‘a’ was here
But if I make the variable global then it works fine.
#include<stdio.h>
int a;
int a = 10;
int main()
{
printf("a is %d \n",a);
return 0;
}
Why is declaring the same global variable twice not an error, but doing that for a local variable is an error?
In C, the statement int a; when made at file scope, is a declaration and a tentative definition. You can have as many tentative definitions as you want, as long as they all match each other.
If a definition (with an initializer) appears before the end of the translation unit, the variable will be initialized to that value. Having multiple initialization values is a compiler error.
If the end of the translation unit is reached, and no non-tentative definition was found, the variable will be zero initialized.
The above does not apply for local variables. Here a declaration also serves as a definition, and having more than one leads to an error.
The other reason I could think of is that un-initialized global variables are stored in the BSS (Block Structured Segment) where are the global variables that are initialized are stored in Data Segment.
I am guessing that there is some kind of a name space resolution and when there is a conflict the variable in the Data segment overrides the one in the Block Structured Segment.
if you were to declare
int a =5
int a = 10
in the global scope (both in the data segment) there would be conflict as expected.
You can't have two global variables with the same name in C program.
C might allow multiple definitions in the same file scope through the tentative definition rule, but in any case all definitions will refer to the same variable.
Local Variable
In C, multiple local variables are not "merged" into one.
All the local variables with the same name will be referring to the different int-sized piece of memory.
#include<stdio.h>
int main()
{
int a;
int a = 10;
printf("a is %d \n",a);
return 0;
}
So when assigning the memory to the redeclaration of the same variable it gives an Error.
Global Variable
In C, multiple global variables are "merged" into one. So you have indeed just one global variable, declared multiple times. This goes back to a time when extern wasn't needed (or possibly didn't exist - not quite sure) in C.
In other words, all global variables with the same name will be converted to be one variable - so your
#include<stdio.h>
int a;
int a = 10;
int main()
{
printf("a is %d \n",a);
return 0;
}
will be referring to the same int-sized piece of memory.
Related
When I compile the code below
#include<stdio.h>
int main()
{
int a;
int a = 10;
printf("a is %d \n",a);
return 0;
}
I get an error:
test3.c: In function ‘main’:
test3.c:6:5: error: redeclaration of ‘a’ with no linkage
test3.c:5:5: note: previous declaration of ‘a’ was here
But if I make the variable global then it works fine.
#include<stdio.h>
int a;
int a = 10;
int main()
{
printf("a is %d \n",a);
return 0;
}
Why is declaring the same global variable twice not an error, but doing that for a local variable is an error?
In C, the statement int a; when made at file scope, is a declaration and a tentative definition. You can have as many tentative definitions as you want, as long as they all match each other.
If a definition (with an initializer) appears before the end of the translation unit, the variable will be initialized to that value. Having multiple initialization values is a compiler error.
If the end of the translation unit is reached, and no non-tentative definition was found, the variable will be zero initialized.
The above does not apply for local variables. Here a declaration also serves as a definition, and having more than one leads to an error.
The other reason I could think of is that un-initialized global variables are stored in the BSS (Block Structured Segment) where are the global variables that are initialized are stored in Data Segment.
I am guessing that there is some kind of a name space resolution and when there is a conflict the variable in the Data segment overrides the one in the Block Structured Segment.
if you were to declare
int a =5
int a = 10
in the global scope (both in the data segment) there would be conflict as expected.
You can't have two global variables with the same name in C program.
C might allow multiple definitions in the same file scope through the tentative definition rule, but in any case all definitions will refer to the same variable.
Local Variable
In C, multiple local variables are not "merged" into one.
All the local variables with the same name will be referring to the different int-sized piece of memory.
#include<stdio.h>
int main()
{
int a;
int a = 10;
printf("a is %d \n",a);
return 0;
}
So when assigning the memory to the redeclaration of the same variable it gives an Error.
Global Variable
In C, multiple global variables are "merged" into one. So you have indeed just one global variable, declared multiple times. This goes back to a time when extern wasn't needed (or possibly didn't exist - not quite sure) in C.
In other words, all global variables with the same name will be converted to be one variable - so your
#include<stdio.h>
int a;
int a = 10;
int main()
{
printf("a is %d \n",a);
return 0;
}
will be referring to the same int-sized piece of memory.
Consider given C codes :
#include<stdio.h>
extern int i;
int main(){
printf("%d", i);
return 0;
}
It gives Compilation error. While if I initialize extern int i=10; then output is 10.
#include<stdio.h>
extern int i=10; //initialization statement
int main(){
printf("%d", i);
return 0;
}
And also, if I assign int i=10;then output is 10.
#include<stdio.h>
extern int i;
int i=10; //assignment
int main(){
printf("%d", i);
return 0;
}
And
#include<stdio.h>
extern int i;
int main(){
int i=10; //assignment
printf("%d", i);
return 0;
}
Variation :
#include<stdio.h>
extern int i;
int i=20;
int main(){
int i=10;
printf("%d", i);
return 0;
}
Since, int i is local variable, so output is 10.
Please, can you explain some important point about extern storage class in C
I read somewhere, a declaration declares the name and type of variable or function. A definition causes storage to be allocated for the variable or the body of the function to be defined. The same variable or function may have many declaration, but there can be only one defition for that variable or function.
Consider
int i;
declared outside all the functions of the programme including main.
This means i will have
file scope
static storage duration
space is allocated for i. #This is important.
Consider
extern int i;
declared outside all the functions of the programme including main.
This means i will have
file scope
static storage duration
i is only declared, not defined which means space is not allocated.
i is assumed to be defined somewhere else, may be, in an include file
Consider
extern int i=10;
declared outside all the functions of the programme including main.
This is the case where you're initializing the extern variable i. In this case
Space is allocated for i.
i will be initialized to 10.
The keyword extern is neglected which means i is NOT declared only.
Note
For extern int i it is mandatory that the variable should be defined somewhere else, ie in another source file. If this is not the case, you will a compile-time error.
The extern storage class specifier is used to give a reference of a global variable that is visible to ALL the program files. When you use 'extern', the variable cannot be initialized however, it points the variable name at a storage location that has been previously defined.
when the code references a symbol via the extern modifier, it means the symbol is actually defined elsewhere rather than in the current file.
An exception, if the extern modififier is used for a symbol that is actually defined in the current file, that is OK.
The extern int i; declaration just tells the compiler that there somewhere (in this or another source) exists an actual declaration of i in global scope. It's not in itself the actual declaration of i. Therefore it's inappropriate to assign a value to i in that declaration (which is why the second try is invalid). Your first attempt is invalid since you don't have an actual declaration of i.
Your third is OK though as you have an actual declaration of i, but you wouldn't have to have the extern int i; declaration.
Your last samples involves i in both local and global scope. In such a case the variable in local scope will be used. That's why you don't get 20 printed.
#include<stdio.h>
int i =0;
i=2;
int main(){
// some Code here
return 0;
}
Error : /Users/vaibhavkumar/Documents/C/primeFactors.c|4|error: redefinition of 'i'|
Why redefinition of the variable is not allowed in C.
Global variables are stored in Data Segment(area of memory), at the same place where static variables are stored. How came static variables can be redeclared ?
That is not redefinition it is assignment.
Assignment is not the same as initialisation in C, and cannot be done outside a function - there is no thread of execution in that context, so when would it be done?
Variables with static linkage are no different to global variables (with extern linkage) in this respect, however static linkage variables are local to a single compilation unit and are not visible externally. If you declare two statics of the same name in separate compilation units, they are entirely independent and unrelated variables - they needn't even be the same type.
Note that static linkage is distinct from static storage, but they use the same keyword. All global and static linkage variables have static storage class implicitly, but a function local variable declared static has static storage class - i.e. it always exists - like a global, but is only visible locally.
Clifford explained the difference between assignment and initialization. But just fore completeness: You're not allowed to do assignments outside functions. Only initializations.
But why do you get this strange error? It's because of implicit declaration.
If we're talking about global space, then this
int i = 0;
i = 2;
is actually equivalent to this:
int i = 0;
int i = 2;
And this code will print 42:
#include <stdio.h>
i = 42;
int main(void) {
printf("%d\n", i);
}
The reason is backwards compatibility. Don't use this "feature"
The logic behind the strange message that seem very unrelated, is kind of like this:
Implicit declarations are allowed
Assignments are not allowed in global space
Therefore, i=2; in global space, must be a declaration
The following program was on a practice worksheet given out in class. We are asked to give its output, but from what I understand about linkage, file2.c should not have two instances of the static identifier b but the program compiles with a warning and runs just fine. My question is, why is this allowed? I thought the point of static linkage was to be able to access an identifier everywhere in that file?
CLARIFICATION: The question is about file2.c: there are two "static int b" declarations. Why is that allowed?
/* file1.c */
#include <stdio.h>
extern int a;
static int b;
void f(int);
void g(void);
int main() {
a = 10;
b = 20;
f(a);
f(b);
g();
printf("main: %d %d\n", a, b);
return 0;
}
/* file2.c */
include <stdio.h>
int a;
static int b;
void f(int c) {
static int b = 5;
a += b;
b += c;
printf("f: %d %d\n", a , b ) ;
}
void g(void) {
a += 5;
b = 10;
printf("g: %d %d\n", a , b);
}
Thank you in advance for any help (this is my first time posting so I apologize if there are formatting errors!).
The compiler creates a different instance for every global static variable, even when you have several such variables with identical names.
In fact, the compiler (or possibly, the preprocessor) implicitly changes the name of every such variable, according to the name of the source file which declares it.
You can prove this to yourself by declaring a global static variable in a header file, and then include this header file in several different source files. Try to set it to a different value in each source file, and you'll see that this variable retains its different value in each source file.
If you want to have the same instance of a global variable accessible in several source files, then you should refrain from declaring it static:
If you declare it in a header file, then use extern as prefix, and include the header file in every source file that makes use of this variable.
If you declare it in a source file, then you will have to declare it as extern in every other source file that makes use of this variable.
The address of an external global variable is determined only during linkage. This is in contrast with the following cases, in which the address of the variable is determined during compilation:
A local variable
A static local variable
A static global variable
A non-external global variable
I believe that the term static linkage refers to the linkage of compiled objects (or libraries) into the executable image during the build process, as opposed to dynamic linkage which refers to the linkage of compiled code (also known as DLL) into the executable image only during runtime.
UPDATE:
After reading your clarification, I understand that the only issue is with a local variable and a global variable of the same name (the static attribute makes no difference with regards to this issue).
Inside a function, a local variable is always "preferred by the compiler" over a global variable with the same name. In other words, in function f, all operations on variable b are applied on the local variable and not on the global variable.
I am surprised with the following behaviour of extern.
When I run this
#include<stdio.h>
int main()
{
extern int a;
printf("%d\n", a);
return 0;
}
int a=20;
OUTPUT: 20(in gcc Linux 32-bit,which seems OK)
But when I declare the variable a inside main():
#include<stdio.h>
int main()
{
extern int a;
int a=20;
printf("%d\n", a);
return 0;
}
OUTPUT:
extern.c: In function ‘main’:
extern.c:5:9: error: declaration of ‘a’ with no linkage follows extern declaration
extern.c:4:16: note: previous declaration of ‘a’ was here
Why I am getting the error now after changing the scope of a from global to local?Why it now doesn't allow redeclaration of a ,whereas it allowed in previous case.
The point of an extern declaration is to tell the compiler about a global variable or function used by multiple compilation units (.c files), but defined and allocated in a single compilation unit. The extern declaration is placed in a header file included by all units, and a single compilation unit contains the actual definition, therefore seeing both.
Your first example is legal C: you are declaring that a will refer to an externally defined variable, and then proceed to define that variable in the current compilation unit. Normally the extern declaration would be included from a header file and therefore appear to the compiler on top-level, not inside the function, but the compiler doesn't care either way. In other words, here there is no redefinition, only definition following declaration.
Your second example declares a to have external linkage, and then proceeds to define it as a local variable in main. The declaration and the definition are obviously incompatible - if a is a local variable, it cannot be defined and allocated in only one place - it will instead be automatically allocated on the stack every time the function is called. This incompatibility results in the error diagnostic.
In the first example, you are telling to the compiler: "hey, I have this variable called a that is defined somewhere else.", and then you use it. That's fine.
#include<stdio.h>
int main()
{
extern int a;
printf("%d\n", a);
return 0;
}
int a=20;
In the second example, you are also telling to the compiler that there is somewhere in the program a variable called a you want to use, and then you declare a new variable with the same name on your stack. That does not make much sense and the compiler says 2 things: can't find any declaration of variable a in the program and variable a already exists (if you fix the first error, it will).
#include<stdio.h>
int main()
{
extern int a;
int a=20;
printf("%d\n", a);
return 0;
}
When you declare a global variable, its memory is allocated when the program is launched (it's in the binary file and mapped in memory). When you declare a local variable, the memory is allocated on the stack, during the execution of the function. You can't refer with extern to a variable that does not exist yet.