This question already has an answer here:
Why extern int a ; initialization giving error locally but not globally? [duplicate]
(1 answer)
Closed 5 years ago.
I surprised when compiled following program on GCC compiler. It's successfully worked. Compiler gives only warning.
warning: 'i' initialized and declared 'extern' [enabled by default] extern int i = 10; ^
My code:
#include <stdio.h>
//Compiler version gcc 4.9
extern int i = 10;
int main()
{
printf("%d\n",i);
return 0;
}
Output:
10
Why doesn't give compiler error? Is it undefined behavior?
You should not put your main function body in a header, but rather in a .c-file. Vice versa, you should not put extern in a .c-file but only in a header. That is the difference between declaration and definition.
Extern means, make this variable known, but there is no memory to be reserved for it. The compiler now says: Ok, I know you want this variable to be used, but it is only promised to be there, not actually defined.
The compiler anyway does not know about other objects (other .c-files) that might define this variable. So it keeps it to the linker to actually try to gather all variables.
If the linker now does not find that variable elsewhere, it implicitly makes the variable local, but warns about the broken C-standard.
Related
This question already has answers here:
In C, is it valid to declare a variable multiple times?
(1 answer)
In C,why is multiple declarations working fine for a global variable but not for a local variable?
(3 answers)
Closed last year.
So far I have understood the following:
A variable declaration is the declaration of a type and name of a variable without allocating memory space for it.
A variable definition means that the variable is declared and memory space is allocated for it.
So it has nothing to do with the initialization of the variable, whether you speak of a definition or a declaration.
In C, a declaration is always a definition e.g. if one write int i;.
But there is one exception. If you write extern int i; no memory space is allocated, only the variable is declared.
So int i; is always declaration and definition at the same time. But extern int i; is just declaration.
Is it true that in C you can declare a variable as often as you want, but you can only define the variable once?
I ask because I've tried the following and the compiler results confuse me. I use gcc and don't set the -std flag.
Neither this program:
int i;
int i;
void main(void){
i = 2;
}
nor this program:
int i=0;
int i;
void main(void){
i = 2;
}
lead to problems. The compiler compiles both without error. I would have expected since I didn't use the "extern" keyword here that the compiler would say something like "error: multiple definition".
But it doesn't give an error message. Is it possible that the compiler automatically writes an "extern" before all global defined "int i;" if I don't initialize them at the same time?
Isn't it then superfluous for the programmer to ever use the extern keyword for variables since the compiler will do that automatically anyway?
I think my considerations are confirmed by the following behavior. The following programs return errors:
int i;
i=0;
void main(void){
i = 2;
}
leads to:
"warning: data definition has no type or storage class
i=0;
warning: type defaults to 'int' in declaration of 'i' [-Wimplicit-int]"
and
float i;
i=0;
void main(void){
i = 2;
}
leads to:
"warning: data definition has no type or storage class
i=0;
warning: type defaults to 'int' in declaration of 'i' [-Wimplicit-int]
error: conflicting types for 'i'
note: previous declaration of 'i' was here
float i;"
So to me again it looks like there is an implicit "extern" before the first int i; respectively float i; is written because they are not assigned a value. As a result, no storage space is allocated for i.
But there is no other file in which storage space is allocated for i. Therefore there is no definition for i and the compiler therefore thinks in the 2nd line that i should be defined here.
Therefore there are no problems with the 1st program because the automatic type assignment fits, but with the 2nd program it no longer fits, which is why an error is returned.
The following program also throws an error:
void main(void){
int i;
int i;
}
If I write the declaration (and thus also the definition) in a scope, the compiler returns the following error message.
"error: redeclaration of 'i' with no linkage int i;
note: previous declaration of 'i' was here int i;"
I can only explain it again with the fact that the compiler does not automatically set an "extern" before a variable that is not a global variable and therefore there are 2 definitions here.
But then I ask myself why is it called redeclaration and not redefinition or multiple definition?
It would be very nice if someone could confirm my assumptions or enlighten me on how to understand it correctly. Many Thanks!
A variable declaration is the declaration of a type and name of a variable without allocating memory space for it.
Even if memory is reserved for an object, it a declaration. We do not exclude definitions from declarations; there are declarations that are definitions and declarations that are not definitions.
The declaration x = 3; causes memory to be reserved for x, but it also makes the name and type of x known, so it declares x.
So int i; is always declaration and definition at the same time.
Not quite. Inside a function, int i; is a definition. Outside of a function, int i; is a tentative definition. This is a special category that was necessary due to the history of C development. The language was not designed all at once with foresight about how it would be used. Different implementors tried different things. When a standard for the C language was developed, the committee working on it had to accommodate diverse existing uses.
When there is a tentative definition, the program can still supply a regular definition later in the translation unit. (The translation unit is the source file being compiled along with all the files included in it.) If the program does not supply a regular definition by the end of the translation unit, then the tentative definition becomes a regular definition as if it had an initializer of zero, as in int i = 0;.
Some C implementations treat multiple tentative definitions of an identifier in different translation units as referring to the same object. Some C implementations treat them as errors. Both behaviors are allowed by the C standard.
Is it true that in C you can declare a variable as often as you want, but you can only define the variable once?
Not always. Variables with no linkage (declared inside a function without static or extern) may not be declared more than once. (An identical declaration can appear inside a nested block, but this declares a new variable with the same name.)
Repeated declarations must have compatible types, and there are additional rules about which repeated declarations are allowed. For example, an identifier may not be declared with static after it has been declared with extern.
The compiler compiles both without error.
As described above, int i; outside a function is a tentative definition. Initially, it acts only as a non-definition declaration. So it may be repeated, and it may be replaced by a regular definition.
So to me again it looks like there is an implicit "extern" before the first int i;
No, there is not. int i; is a tentative definition, and it has nothing to do with the error messages you are getting. The error messages “data definition has no type or storage class” and “type defaults to 'int' in declaration of 'i'” are from the i=0;. This is a statement, not a declaration, but the C grammar does not provide for statements outside of functions. Outside of functions, the compiler is looking for only declarations. So it expects to see a type, as in int i=0;. The first message tells you the compiler does not see a type or a storage class. The second message tells you that, since it did not see a type, it is assuming int. This is a relic of old behavior in C where the int type would be taken as a default, so it could be left off. (Do not use that in new C code.)
The following program also throws an error:
Inside a function, int i; is a definition, so two of them causes multiple definitions of i.
This question already has answers here:
Why is creating a variable using 'extern' a declaration and not a definition?
(5 answers)
Closed 2 years ago.
I'm sorry for what I'm sure is a simple mistake. But after a few hours I can't figure out what I'm doing wrong. I understand that extern needs to be declared outside a function and defined within a function. But I can't get it to work.
Here is my minimal code error.
extern double d;
int main(void) {
d = 0;
return 0;
}
/home/0KzRYK/ccCTD3Lf.o: In function `main':
prog.c:(.text.startup+0x3): undefined reference to `d'
collect2: error: ld returned 1 exit status
Thank you all for the comments. My mistake was to assume that extern double d defines the variable in the same way as double d. But apparently it doesn't.
I would say this is a non-intuitive property of the language, at least for a beginner (eg. extern double isn't a definition but static double is).
Following your comments I found a related question that talks exactly about this: Why is creating a variable using 'extern' a declaration and not a definition?
Your understanding is wrong. Variables with extern need not be defined within a function. But it must be defined somewhere (maybe another source file).
Example:
main.c:
extern double d;
int main(void) {
d = 0;
return 0;
}
d.c:
double d;
compilation:
gcc -o main main.c d.c
This question already has answers here:
Why does initializing an extern variable inside a function give an error?
(5 answers)
Closed 6 years ago.
extern int a = 10; // it is not giving error
int main ()
{
extern int b = 10; //it is giving error
return 0;
}
error: ‘b’ has both ‘extern’ and initializer
extern int b = 10;
Referring to C11 (N1570) 6.7.9/5 Initialization:
If the declaration of an identifier has block scope, and the
identifier has external or internal linkage, the declaration shall
have no initializer for the identifier.
The rule is placed within constraints section, so any conforming compiler should reject the code, that violates it.
The point of extern keyword at the block scope is to declare some existing object from outside scope. It would not make much sense to declare an object and give it some other value at the point of declaration.
The recommended way of declaring external objects is to put their declarations at the file scope (at the top of source code), thus they are easy to spot and manage by maintenance programmer.
This question already has answers here:
How do I use extern to share variables between source files?
(19 answers)
Closed 7 years ago.
I get very confused with the static and extern storage classes. I do not understand what is wrong with the below code snippet. I expect the printf to print the value Zero. The build is failing with the error "Undefined reference to 'i' ". I expect the statement "extern int i" to be a valid C statement. Is it not?
#include<stdio.h>
void main()
{
extern int i;
printf("%d", i);
}
In the function main
extern int i;
is a declaration of i, not definition. It must be defined somewhere.
#include<stdio.h>
int i; //definition
int main()
{
extern int i; //declaration
printf("%d", i);
}
In this example, the declaration is valid, but can be omitted.
When you declare a variable as extern inside a function, the compiler thinks that the variable is defined in some other translation unit. If it's not defined anywhere else, then you will get a linker error saying that the linker can't find the variable.
see when you are using extern storage class in the main then our compiler use to search the declaration of the variable in the perticular location ,here extern stands for compiler that this variable is declared at any location in the program it can be local or outside the scope , if it dont found any declaration then it gives this linking error becoz it is unable to found the variable declaration.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Redefinition allowed in C but not in C++?
#include<stdio.h>
int i;
int i;
int main()
{
// int i;
// int i;
printf("%d\n",i);
return 0;
}
~
The above code runs wihtout giving any error gcc -Wall -Werror demo.c -o demo
But when I uncomment the local i variables the comment out the global i ,It gives me errors .
In function ‘main’:
demo.c:7:6: error: redeclaration of ‘i’ with no linkage
demo.c:6:6: note: previous declaration of ‘i’ was here
What is this local global concept here ?, Anybody Please explain.
In C99 (see more specifically section 6.2), global declarations have by default external linkage (6.2.2§5). In that case (6.2.2§2), both declarations of i refer to the same object. On the contrary, local variables have no linkage (6.2.2§6), and are thus supposed to refer to unique identifiers (again 6.2.2§2): you would thus end up with two local variables of the same name in the same scope, which is not allowed (6.2.1§5: Different entities designated by the same identifier either have different scopes, or are in different name spaces)
You can have more than one definition of your variable in a global scope, if all definitions agree (all have the same type) and the variable is initialized in not more than one place.
J.5.11 Multiple external definitions
There may be more than one external definition for the identifier of an object, with or without the explicit use of the keyword extern; if the definitions disagree, or more than one is initialized, the behavior is undefined (6.9.2).