Global variable declaration in c [duplicate] - c

This question already has answers here:
Tentative definitions in C and linking
(3 answers)
Closed 6 years ago.
#include<stdio.h>
int check,check;
void main(){
printf("Hello!!");
}
When I compile this piece of code, everything goes on normal but when I give this inside the main function,
#include<stdio.h>
void main(){
int check,check;
printf("Hello!!");
}
I get an error like
C:\MinGW\bin>cc ex1.c
ex1.c: In function 'main':
ex1.c:4:11: error: redeclaration of 'check' with no linkage
int check,check;
^
ex1.c:4:5: note: previous declaration of 'check' was here
int check,check;
^
Why is it so?

This is possible in global scope, because that is considered an tentative definition.
Quoting C11, chapter §6.9.2
A declaration of an identifier for an object that has file scope without an initializer, and
without a storage-class specifier or with the storage-class specifier static, constitutes a
tentative definition.
However, in the block scope (function scope), there's no tentative definition, hence the code tries to create two identifiers with the same name which is cause for the re-declaration error, because they actually denote the same object.
You can read more about it here.
That said, since C99, for hosted enviroments, void main() is not a valid signature anymore, it has to be int main(void) at least.

Related

Why am i not getting re-declaration error in global scope [duplicate]

This question already has answers here:
About Tentative definition
(2 answers)
Closed 1 year ago.
This code gives me no re-declaration error.
#include<stdio.h>
int i;
int i = 27;
int main()
{
printf("%d",i);
return 0;
}
According to me I declared and defined an uninitialised global variable with 0 as default value.
And later re-declared, redefined and assigned it 27 value.
I was expecting it to give a re-declaration error because both i's are in same scope(global).
But I'm not getting any error why?
But below code gives me a re-declaration error as expected because of defining them in same scope.
#include<stdio.h>
int main()
{
int i;
int i = 27;
printf("%d",i);
return 0;
}
At file scope, this:
int i;
Is a tentative definition since there is no initializer. It will be considered an external definition if no other definition appears.
When you then do this:
int i = 27;
This constitutes an external definition for i which matches the prior tentative definition.
These terms are defined in section 6.9.2 p1 and p2 of the C standard:
1 If the declaration of an identifier for an object has file scope and an initializer, the declaration is an external
definition for the identifier.
2 A declaration of an identifier for an object that has file scope without an initializer, and without a storage-class
specifier or with the storage-class specifier static, constitutes a
tentative definition. If a translation unit contains one or more tentative definitions for an identifier, and the translation unit
contains no external definition for that identifier, then the
behavior is exactly as if the translation unit contains a
file scope declaration of that identifier, with the composite type
as of the end of the translation unit, with an initialize requal to 0.
Your second code snippet defines a variable in block scope (not file scope), then defines it again in the same scope. That constitutes a variable redefinition.
In C this declaration in the file scope without an initializer
int i;
is a declaration of a variable and not its definition, So the next declaration
int i = 27;
is the definition of the variable.
You may declare a variable without its definition in a file scope several times though the declarations can be redundant.

Why extern int a ; initialization giving error locally but not globally? [duplicate]

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.

Variable access across multiple files [duplicate]

This question already has answers here:
Use of 'extern' keyword while defining the variable
(2 answers)
Closed 8 years ago.
I was trying out programs based on extern and as I understand, this is helpful when accessing variables across multiple files having only one definition.
But I tried a simple program as below without extern and thing seem to work when I expected it would fail during linking process
file5.c:
#include <stdio.h>
#include "var.h"
int a = 20;
int main() {
printf("\n File5.c a = %d", a);
test();
return 0;
}
file6.c:
#include <stdio.h>
#include "var.h"
int test() {
printf("\n File6.c a = %d",a);
}
var.h
int a;
As I have included var.h in all header files without extern, int a would be included in both the .c file and during linking, compiler should have thrown a warning or error message but it compiles file without any issue.
Shouldn't var.h have the following extern int a?
It is generally best if the header uses extern int a;. See also How do I share a variable between source files in C?
The standard says:
ISO/IEC 9899:2011 §6.9.2 External object definitions
Semantics
¶1 If the declaration of an identifier for an object has file scope and an initializer, the
declaration is an external definition for the identifier.
¶2 A declaration of an identifier for an object that has file scope without an initializer, and
without a storage-class specifier or with the storage-class specifier static, constitutes a
tentative definition. If a translation unit contains one or more tentative definitions for an
identifier, and the translation unit contains no external definition for that identifier, then
the behavior is exactly as if the translation unit contains a file scope declaration of that
identifier, with the composite type as of the end of the translation unit, with an initializer
equal to 0.
Thus, what's in the header is a tentative definition of the variable. At the end of the translation unit (TU) for file5.c, you have no longer got a tentative definition; the 'external definition' specified by int a = 20; has specified that. At the end of the TU for file6.c, you have a definition equivalent to int a = 0;.
When you try to link file5.c and file6.c, you should run into multiple definitions of a. However, there is a common extension, documented in the standard in Annex J:
J.5.11 Multiple external definitions
¶1 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).
Your compiler is providing the extension identified by §J.5.11, and therefore (legitimately) not complaining.
580

Double definition of variable [duplicate]

This question already has answers here:
About Tentative definition
(2 answers)
Closed 9 years ago.
As we know extern declaration of variables can be initialized.
#include<stdio.h>
extern int a=5; //will work as both definition and declaration.
int main()
{
}
Why this programme is compiling and running with no error.
extern int a=5; //will work as both definition and declaration.
int main()
{
}
int a; // isn't it second definition??
C has a concept of a "tentative definition". Most definitions without initializers are "tentative", so an arbitrary number of them are allowed, as long as they don't conflict with each other. At the end of the translation unit, the definition of the variable becomes basically the composite of those (e.g., if one definition says the variable is const and another says it's volatile, the variable will end up as both const and volatile.
A definition with an initializer is never tentative, so only one of them is allowed.

What is this double declaration mean in C? [duplicate]

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).

Resources