Are the following declarations correct?
Outside any function:
int a; //external by default
extern int a; //explicitly extern
static int a; //explicity static
const int a; //static by default
static const int a; //explicitly static
extern const int a; //explicitly extern
Inside a function:
int a; //auto by default
static in a; //explicity static
const int a; //static by default
static const int a; //explicitly static
Close.
Anything at global scope (ie: outside a function) is static by default.
eg:
//main.c
int myVar; // global, and static
int main(void) {
...
return 0;
}
//morecode.c
extern int myVar; //other C files can see and use this global/static variable
However, if you explicitly declare something at the global scope as static, not only is it static, but it is only visible inside that file. Other files can't see it.
//main.c
static int myVar; // global, and static
int main(void) {
...
return 0;
}
//morecode.c
extern int myVar; // compiler error; "myVar" can only be seen by
// code in main.c since it was explicitly
// declared static at the global scope
Also, nothing is "extern" by default. You typically use extern to access global variables from other files, provided they weren't explicitly declared static as in the example above.
const only implies that the data cannot change, regardless of it's scope. It does not imply extern, or static. Something can be "extern const" or "extern", but "extern static" doesn't really make sense.
As a final example, this code will build on most compilers, but it has a problem: myVar is always declared "extern", even in the file that technically creates it. Bad practice:
//main.c
extern int myVar; // global, and static, but redundant, and might not work
// on some compilers; don't do this; at least one .C file
// should contain the line "int myVar" if you want it
// accessible by other files
int main(void) {
...
return 0;
}
//morecode.c
extern int myVar; //other C files can see and use this global/static variable
Finally, you might want to cover this post on the various levels of scope if you are not already familiar with them. It will likely be helpful and informative to you. Good luck!
Terminology definition - Scope in C application
The person who answered this question of mine on scope did a good job, in my opinion.
Also, if you declare something static within a function, the value remains between function calls.
eg:
int myFunc(int input) {
static int statInt = 5;
printf("Input:%d statInt:%d",input,statInt);
statInt++;
return statInt;
}
int main(void) {
myFunc(1);
myFunc(5);
myFunc(100);
return 0;
}
Output:
Input:1 statInt:0
Input:5 statInt:1
Input:100 statInt:2
Note that the use of a static variable within a function has a specific and limited number of cases where they are useful, and generally aren't a good idea for most projects.
One misconception you have appears to be that extern is the opposite of static. This is not the case. You have this:
int a; //extern by default
That's not "extern by default". An extern declaration means that the actual variable definition is elsewhere. So if you have this in your source file:
extern int a;
Then somewhere else you have another source file with:
int a;
Otherwise, if you compile your code you'll get:
/tmp/cc3NMJxZ.o: In function `main':
foo.c:(.text+0x11): undefined reference to `a'
collect2: ld returned 1 exit status
static outside of a function definition means that the variable is only visible to other code defined in the same file. The absence of static means that the variable is visible globally to code that might link against your object file.
I am less certain, but I don't believe that const implies static. That shouldn't be too hard to test.
...and indeed, a very simple test confirms that const does not imply static.
You have to separate the concepts of storage duration and linkage. extern and static, in various contexts, can have effects on both of these properties and other effects but aren't the sole determiner of any of them.
At file scope
int a;
This is a tentative definition. a has static storage duration and external linkage.
extern int a;
A declaration but not a definition. static storage duration and external linkage (or the linkage determined by a prior declaration if one is visible).
static int a;
A tentative definition. static storage duration and internal linkage.
const int a;
A tentative declaration. static storage duration and external linkage (unlike C++).
static const int a;
A tentative definition. static storage duration and internal linkage.
extern const int a;
A declaration and not a definition. static storage duration and external linkage (or the linkage determined by a prior declaration if one is visible).
In block scope
int a;
Definition. automatic storage duration and no linkage.
static int a;
Definition. static storage duration and no linkage.
const int a;
Definition. automatic storage duration and no linkage.
(I think this is strictly legal but not very useful as you can't modify a's indeterminate initial value without causing undefined behavior.)
static const int a;
Definition. static storage duration and no linkage.
(Again, not very useful!)
Related
This question already has answers here:
What is the difference between a definition and a declaration?
(27 answers)
Closed 5 years ago.
Can you please someone explain me the flow of below problem,
#include <stdio.h>
int main(){
extern int a;
printf("%d\n",a);
return 0;
}
int a = 20;
and the output is 20. I am not sure where is the variable a getting defined and where is it getting declared?
The variable a is declared and defined as a global variable in the line:
int a = 20;
The extern line just tells the main() function scope that a is defined in another place.
In this case, the use of extern is not really necessary. You could just declare and define a before the main() function, and then main() would be familiar with it.
Usually, you would use extern when you want to use a variable or a function that was defined in another source file (and not just later in the same source file).
The C programming language has been designed to be one-pass, so that the compiler could process each line only once from top to bottom. So considering your program:
#include <stdio.h>
int main(){
extern int a;
printf("%d\n",a);
return 0;
}
int a = 20;
The identifier a is declared twice, and defined once.
Before the 4th line extern int a;, the compiler doesn't know anything about the identifier a. The declaration extern int a; has the block scope within the function main, and it declares the identifier a as an int and that its storage duration is static and linkage is external. So the compiler can write code that access a global identifier by name a as an int variable that could be defined in another module (external linkage). This is what the compiler does on line 5 when it is used in printf.
Finally at line 9, int a = 20; is another declaration and definition. This declares and defines a as a int with static storage duration, and external linkage.
If you'd put the int a = 20; before the main, the declaration extern int a; would be useless, because it doesn't add anything. I tend to put my main and other depending functions last in my source code, so that minimal amount of extra declarations are needed.
extern is syntactically a "storage class" keyword. But there is no such storage class. C has "static storage", "dynamic storage (malloc, etc) and "automatic storage" (local variables, usually represented using a stack).
If an identifier is declared extern inside a block scope, it means that the declaration refers to an external definition. If the entity being declared is an object, then it has static storage, simply because external objects have static storage. It can be a function too; functions aren't said to have storage.
In C, there is a concept called "linkage". Objects declared outside of any function at file scope, and functions, can have "external" or "internal" linkage.
If we have extern in a block scope, as you have in the example program, there can be a prior declaration of the same name at file scope, or in a nested scope, like this:
static int x;
/* ... */
{
extern int x;
}
Here, the inner x refers to the outer x, and, in spite of being "extern", it has internal linkage because of the "static".
In a nutshell, extern usually means "refer to the earlier declaration, and if there isn't one, declare this as an identifier with external linkage".
The word "external" refers to two separate concepts: the aforementioned "external linkage" and also to the meaning "outside of any function", as in "external declaration". Confusingly, "external declarations", like the static int x above, can have "internal linkage"!
In your program, things are correct because the block scope extern declaration of a and the later int a = 20, which are in separate scopes, happen to independently agree with each other.
The int a = 20; is an external declaration, which is also an external definition (because of the initializer). Since in that scope, no prior declaration of a is visible, it gets external linkage.
So, where is a defined? It is defined as an object with external linkage, in the entire translation unit as a whole. That translation unit is what defines a. a is declared in every place of the program where a declaration appears; and its definition is also a declaration. It is declared in main and also in the last line of the translation unit's source code.
A "declaration" is syntax which makes a name known in some scope. It's a concept that is active during the translation of a program. A "definition" is the fact that some object or function is provided in some translation unit. Translated units still provide definitions, but need not retain information about declarations. (Which is why when we make libraries, we provide header files with declarations in them!)
From the point of view of your main function, that function doesn't "care" where a is defined. It has declared a in such a way that if a is used, then an external definition of a, with external linkage, must exist. That definition could come from anywhere: it could be in the same translation unit, or in another translation unit.
When ever you declare a variable as extern then It means that Variable is declared as global and you cannot initialize the variable there.Because no memory is allocated for that variable It is just declared as a Variable
you can define it some where in your code.
Let us take an example ..consider the code
int main()
{
extern int i;
i=10;
printf("%d",sizeof(i));
}
here you get an error that int 'i' is not defined
therefore you need to write it as:
int main()
{
extern int i;
int i=10;
printf("%d",sizeof(i));
}
In case of your code:
This is declaration
extern int a;
This is definition:
int a = 20;
The storage class extern specifies storage duration and linkage of the object the identifier refers to:
The storage duration is set to static, which means the variable is alive for the whole time the program runs. As you declare that variable inside a function scope, this matters in your example, because in function scope, the default storage duration would be automatic.
The linkage is set to external, this just means different translation units of the same program can share the object. It has the side effect that a definition in another (file) scope is acceptable, as shown in your example. This is a logical consequence of the shared nature, you would typically declare a variable with external linkage in all translation units using it, but define it only in one.
I have one doubt if i declared global variable with static.
file1.c
static int a=5;
main()
{
func();
}
can it be access in another file2.c using extern ?
file2.c
func()
{
extern int a;
printf(a);
}
or only global variable declared without static can be access using extern?
No!
static limits the scope of the variable to same translation unit.
static gives the variable an Internal Linkage and this variable cannot be accessed beyond the translation unit in which was created.
If you need to access a variable accross different files just drop the static keyword.
No. A a in file1.c names a variable with internal linkage. The same name used from a different translation unit will refer to a different variable. That might also have internal linkage or it might (as in this case) have external linkage.
Within the same file you can refer to a file scoped variable with internal linkage with extern, though.
static int a;
int main(void) {
extern int a; // still has internal linkage
printf("%d\n", a);
}
That seems to be a misunderstanding of the two meanings of static:
for global declarations static means restriction to translation unit, so static is exactly meant to prevent what you are trying to do
for local variables static is a storage class, meaning that the variable keeps its value between function calls. For global variables (on module level, i.e. outside of functions) this is always the case, so static is not needed.
#include <stdio.h>
static i = 5;
int main()
{
extern int i;
printf("%d\n",i);
return 0;
}
Can someone give any use-case for declaring a static variable as extern inside a function block?
NEW:
Why is this not allowed?
int main()
{
static i = 5;
extern int i;
printf("%d\n",i);
return 0;
}
this is useful when you need to access a variable that resides within another translation unit, without exposing the external variable globally (for a few reasons, like name collision, or that the the variable shouldn't be directly accessed, so static was used to limit its scope, but that TU's header still needs access).
As an example, lets say we have a translation unit foo.c, it contains:
//foo.c
static int i = 0;
i shouldn't be changed or directly accessed outside foo.c, however, foo.h comes along requiring access to i for an inline function, but i shouldn't be exposed to any translation unit using foo.h, so we can use extern at functional level, to expose it only during the scope of IncI, the inline function requiring the use of i:
//foo.h
inline void IncI(int val)
{
extern int i;
i += val;
}
Your second example is 'disallowed' because the compiler thinks you are trying to bind two different variables to the same symbol name, ie: it creates the static i at local scope, but searches for the extern int i at global scope, but doesn't find it, because static i as at the function scope. a more clever compiler would just fix the linkage to the static i, whether or not this follows standards I wouldn't know.
Now that I have a C standards document to work from (shame on me I know...), we can see what the official stance is (in C99):
6.2.2 Linkages of identifiers
Section 3:
If the declaration of a file scope identifier for an object or a function contains the storageclass
specifier static, the identifier has internal linkage.
Section 4:
For an identifier declared with the storage-class specifier extern in
a scope in which a prior declaration of that identifier is visible,
if the prior declaration specifies internal or external linkage, the
linkage of the identifier at the later declaration is the same as the
linkage specified at the prior declaration. If no prior declaration is
visible, or if the prior declaration specifies no linkage, then the
identifier has external linkage.
thus, because static will cause internal linkage, the extern will bring that linkage into the current scope. there is also a footnote stating that this may cause hiding of variables:
23) As specified in 6.2.1, the later declaration might hide the prior declaration.
In your second case, you are telling the compiler you have a static (local) variable i and another (global) variable i that is defined somewhere else.
After seeing this answer
I have this doubt.
In my project,
I have seen some extern variables declared and defined like below:
file1.h
extern int a;
file1.c
extern int a=10;
But in the link I mentioned it says that in the c file it should be defined like:
int a = 10;
Does adding extern key word during the definition too has any purpose/meaning.
Or does it matter by the way?
It does not change the meaning. extern only makes sense when you declare a variable. Defining a variable with extern is the same because all global variables that are not marked static are symbols visible to the linker by default.
Note that if you didn't want to initialise the variable, that is, not having the part = 10, the compiler will assume that extern int a is always a declaration and not a definition. In the same sense, having int a globally is always a definition and not just a declaration.
It depends. In this case, it makes no difference, but it can.
There are two issues here: definition vs. just declaration, and linkage.
And C++ doesn't handle them in an orthogonal manner. In C++, the
declaration of a variable or a reference is a definition if and only if
neither the extern keyword nor an initialization are present. (Note
that the rules are different for functions, types and templates.) So:
extern int a; // not a definition
int a; // definition
extern int a = 42; // definition
int a = 42; // definition
The rules say you must have exactly one definition, so you put a
definition in a source file, and the declaration in a header.
With regards to linkage, a symbol declared as a variable or a reference
has external linkage if it is declared at namespace scope, is not
declared static, and is either not const (nor constexpr in C++11)
or has been declared extern. The fact that const can give a
variable internal linkage occasionally means that the extern is
necessary:
int const a = 42; // internal linkage
extern int const a = 42; // external linkage
Note that the extern doesn't have to be on the same declaration:
extern int const a; // declaration, in header...
int const a = 42; // external linkage, because of
// previous extern
Still, I've occasionally needed the extern; typically because I want
to use a local constant to instantiate a template. (This is only an
issue if the template parameter takes a pointer or a reference. You can
instantiate a template with an int parameter with an int const a =
42;, because the template is instantiated with the value 42, and not
the variable a.)
While I was reading the answers of Use of 'extern' keyword while defining the variable
One of the user answered these way
extern int a; // not a definition
extern int a = 42; // definition
I was expecting both are not definitions but declarations. I was thinking Both statements says that the variable is defined outside the function and we have to use extern keyword to use it. is this a mistake by him or is it really a definition ?
I know that
extern int a; // variable is already defined but its outside the function
extern int a=42 ; //I guess a variable is assigned a value but not a definition
but these statement
extern int a = 42; // user said its a definition and now i got confused
Please clear me with these.
Whenever initialisation is attempted, the statement becomes a definition, no matter that extern is used. The extern keyword is redundant in such a case because, by default, symbols not marked static already have external linkage.
It doesn't make sense to declare an external variable and set its initial value in the current compilation unit, that's a contradiction.
extern int a; is a declaration. It does not allocate space for storing a.
extern int a = 42; is a definition. It allocates space to store the int value a and assigns it the value 42.
here the variables are declared inside the main() function where its definition was defined outside in the global declaration section
extern int a; //This is a declaration
extern int a=42; //This is a definition