Why won't extern link to a static variable? - c

Why does extern int n not compile when n is declared (in a different file) static int n, but works when declared int n? (Both of these declarations were at file scope.)
Basically, why is int n in file scope not the same as static int n in the same scope? Is it only in relation to extern? If so, what about extern am I missing?

The whole and entire purpose of static is to declare that a variable is private to the source file that it is declared in. Thus, it is doing precisely its job in preventing a connection from an extern.
Keep in mind that there are four flavors of file-scope variable definition:
int blah = 0; — blah is defined in this file and accessible from other files. Definitions in other files are duplicates and will lead to errors.
extern int blah; — blah must be defined elsewhere and is referenced from this file.
int blah; — This is the moral equivalent of FORTRAN COMMON. You can have any number of these in files, and they are all resolved by the linker to one shared int. (*)
static int blah; (optionally with an initializer) — This is static. It is completely private to this file. It is not visible to externs in other files, and you can have many different files that all declare static TYPE blah;, and they are all different.
For the purists in the audience: 'file' = compilation unit.
Note that static inside functions (not at file scope) are even more tightly scoped: if two functions declare static int bleh = 0; even in the same file, they are unrelated.
(*): for those of you not familiar: in the usual pattern, one compilation unit has to define a global variable, and others can reference it. It 'lives' in that compilation unit. In case (3), above, no file (or all the files) defines it. If two files say int blah = 0;, the linker will complain of multiple definitions. If two files say int blah; the linker cheerfully creates a single global int and causes all the code to refer to it.

In standard C, there are two scopes for variables declared outside of a function. A static variable is only visible inside the compilation unit (i.e., file) that declared it, and non-static variables are visible across the whole program. An extern declaration says that the variable's location isn't known yet, but will be sorted out by the linker; it's compatible with non-static variables, but extern static is just crazy talk!
Of course, in practice there are other visibilities these days. In particular, there are now scoping levels between that of a single source file and a whole program; the level of a single shared library is a useful one (settable through mechanisms like GCC function attributes). But that's just a variation on the theme of non-static variables; static keeps the same interpretation it had before.

According to MSDN documentation:
When modifying a variable, the static keyword specifies that the variable has static duration (it is allocated when the program begins and deallocated when the program ends) and initializes it to 0 unless another value is specified. When modifying a variable or function at file scope, the static keyword specifies that the variable or function has internal linkage (its name is not visible from outside the file in which it is declared).
Static (C++) on MSDN: Archived in January 2015; see also the latest documentation: static § Storage classes (C++) | Microsoft Docs

iv.c:2:1: error: multiple storage classes in declaration specifiers
extern static int i;
^
That is what we get on attempting to extern a static variable. Declaring extern static int i; - is analogous to the declaration float int i;
You can't have float and int appear in the same declaration right? Similarly, you can't have extern and static in the same declaration.

Related

Shall an variable with external linkage be defined with keyword external?

From https://www.quora.com/What-are-the-types-of-linkages-in-C-programming
External linkage, means that the variable could be defined somewhere
else outside the file you are working on, which means you can define
it inside any other translation unit rather your current one (you
will have to use the keyword extern when defining it in the other
source code).
Internal linkage, means that the variable must be defined in your
translation unit scope, which means it should either be defined in any
of the included libraries, or in the same file scope.
None linkage, points to the default functions and braces scopes, such
as defining an auto variable inside a function, this will make the
variable only accessable within that function's scope.
Note that:
Any global object is externally linked by default, you can disable that by using the keyword static.
Any constant global object is internally linked by default, you can
disable that by using the keyword extern.
Suppose a global variable is defined in file1 and I want to use it in file2.
In file1, shall the global variable be defined with keyword
extern?
The quote above seem to contradict itself:
"you will have to use the keyword extern when defining it in the other source code" seems to say it should.
"Any global object is externally linked by default" seems to say that it doesn't need to.
In file2, shall I declare global variable with keyword extern?
tldr: You should declare the variable, with extern, in a header file which is included by both file1 and file2. You should then define the variable in file1 only. To define the variable, you declare it without extern (and also without static).
You sound like you have gotten the extern keyword and the standardese term "external linkage" mixed up.
A variable with "external linkage" is accessible from any function in the program, as long as a declaration of the variable is visible to that function. In contrast, a variable with "internal linkage" is accessible from, at most, one "translation unit" (a single source file and all the files it includes), and a variable with "no linkage" is only visible within a single function. (I don't remember off the top of my head whether a static variable declared within a function is considered to have internal linkage or no linkage.)
The extern keyword, applied to a variable declaration, has two effects. First, it guarantees that that variable will be given external linkage, even if the declaration is inside a function (don't do that). Second, and much more importantly, it makes the declaration not be a definition. What that means is, if you have these two files
/* file1.c */
extern int foo;
/* file2.c */
extern int foo;
int main(void) { return foo; }
their combination is not a valid program. You will get an error from the linker, probably reading something like "undefined reference to foo".
To make this a valid program, you must remove the extern from one of the two declarations of foo. That declaration then becomes a definition, and the program will link. (Also, that declaration can then be given an initializer, if you want it to have a value other than 0 at startup.)
If you remove the extern from both of the definitions of foo, the result is, IIRC, implementation-defined. Some C compilers will merge them into a single global variable, and others will issue a link-time error. Sometimes the behavior depends on whether or not the variables have initializers.
It is OK to write
/* file1.c */
extern int foo;
/* file2.c */
extern int foo;
int foo;
This allows you to put the extern declaration in a header file that both .c files include, which reduces the risk of the declarations coming to have inconsistent types (if this happens, the program will exhibit undefined behavior).
c11 draft, 6.2.2, 4th section, states:
For an identifier declared with the storage-class specifier extern in a scope in which a
prior declaration of that identifier is visible,31) 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.
i don't think there will be any difference with or without extern keyword. some experiment also indicates that:
following 2 compiled:
extern int a;
extern int a;
int a = 20;
and
extern int a;
int a;
int a = 20;
but not this one:
extern int a;
int a = 10;
int a = 20;
however, i have some impression that once i read about the different behavior when dynamic linkage get involved in windows. I cannot find it though. it would be nice if anyone can confirm.
The text you quoted has a lot of errors. I would recommend not relying on information from that site.
(you will have to use the keyword extern when defining it in the other source code).
Not true, as file-scope definitions have external linkage unless the static keyword is used (or no specifier is used and they are re-declaring something already declared with the static keyword).
It is possible to include a redundant extern in the definition, however there must also be an initializer (otherwise it would be a declaration and not a definition).
Internal linkage, means that the variable must be defined in your translation unit scope, which means it should either be defined in any of the included libraries, or in the same file scope.
Presumably this means "included headers", not "included libraries".
Any constant global object is internally linked by default, you can disable that by using the keyword extern.
This is wrong, "global objects" have external linkage unless declared with static. The author might be mixing up C with C++ (in the latter, const global objects have internal linkage unless otherwise specified).
Suppose a global variable is defined in file1 and I want to use it in file2.
// file1.h (or any other header)
extern object_t obj;
// file1.c
#include "file1.h"
object_t obj; // or: extern object_t obj = { 1, 2, 3 };
// file2.c
#include "file1.h"

Get value of static variables in inline functions?

May be my question is a little bit silly, but I can't get this code to work correctly. I have read similar question with answers, but there were a little bit different situation.
So, the question is: "Is it possible to get static variable value in inline functions?"
I code the program for microcontroller with small amount of memory and low speed. For some reason I need to make some functions inline (to save memory and time of execution).
This is the problem description:
For example, I have three files in my program: main.c, some.h, some.c .
In some.c:
#include "some.h"
static int foo;
[... other functions that uses "foo"]
In some.h:
#ifndef SOME_H_
#define SOME_H_
static int foo;
inline int __attribute__((always_inline))
get_foo(void){
return foo;
}
#endif
In main.c:
#include "some.h"
int bar;
int main(void){
bar = get_foo();
return bar;
}
When I tried to compile, I'm getting following:
warning: 'foo' is static but used in inline function 'get_foo' which is not static
When I tried to put extern static int foo; to some.h, I got:
error: multiple storage classes in declaration specifiers
error: static declaration of 'foo' follows non-static declaration
I need to get values of "static" variables from external file in "inline" functions. I want to keep them "static" to separate from main code, as local variable. Is it a way to do this correctly?
Thank you in advance!
EDIT:
To be more clear: I need to get the the value of a variable in one file (some.c) in another file (main.c) by inline function. If the function get_foo() is NOT "inline", everything works perfect, but it takes more memory and execution time.
In this case, static means the variable foo will be a different foo in each source file. If you change static int foo; to extern int foo; in the header and then have a single int foo; in one .c file, I think the compiler warning will go away and your inline function will work fine.
At file scope, static hides a name from the linker so you effectively have different variables in each file.
extern static int foo; is just a mistake. It means, there is something called foo in some other file that I want you to link to, but the name is hidden. The compiler is just saying "forget it".
There is no point for defining a static variable in a header file. Every time you include that header file you will get a new fresh copy of the variable...
Why you don't just define it as
extern int foo;
This way you will have the variable available from any source that included the header
Your request for inlining is in some way incompatible with the internal linkage of the variable.
You have a static variable which means that this variable is only visible in that file.
On the other you have an inline function. If this function would be inlined somewhere else than in this file, then it would refer to another foo variable, which is probably not what you want; at least the compiler warns you about it. It suggests you to change the visibility of that function to static, as to only be available in the same entity than foo.
In another try, you add extern, but this is incompatible with static visibility, choose, extern or static. Read about linkage and visibility rules in C language, for more information.
You also suggest to add foo in some header, which is not a good idea, headers are reserved for declaration of objects not definition. You are encouraged to add type definition in headers, external declaration of objects; but discouraged from define objects (while not strictly forbidden, this would too often lead to clashes).
If you want to have your variable static in a specific translation unit, an inline function that would "live" in another translation unit would never be able to access this static object. That is why access to static objects from inline functions is not allowed, the semantics of what that would mean is simply not clear.
You can either define an extern function that provides the value of its TU where it is defined, or static function(s) with different instantiations in every TU that provide just the value, there.

extern declaration and definition in C

a global variable may one to two different storage classes in C, to my best knowledge, and the declaration may be given with two different keywords, correspodingly
extern int foo; //default
static int bar;
Static variables are only visible within the module of declaration, and cannot be exported. In case of extern declaration, the variable is in the common namespace of all modules linked, unless shadowed by static variable.
Whereas static variables have to be defined in their module, an extern variable may be defined somewhere else. It has to be defined if ever used.
My compiler (GCC) accepts
static int bar = 5;
but casts a complain at
extern int foo = 4;
It seems to be expected that extern variables are never defined with the keyword 'extern'. This leads to the following question:
What kind of storage class does the Object 'foo' in the example above have in the module where it is defined?
IIRC, extern is more of a hint to the compiler that it does not have to allocate storage for the value. The linker is expected to find the value in another compilation unit. Usually extern is used in header files to indicate that the someone has defined storage associated with the name. The definition of the value does not include the extern keyword since the compiler has to allocate storage for the value in the compilation unit that includes the definition.
See extern storage class specifier for more details.
The extern variable will be defined with a global scope (exported) in the unit where it is defined:
int baz = 5;
The default storage class is auto.
Actually you missed two storage classes: auto and register
Register doesn't matter here but the default storage class is auto.
Auto reserves space for a variable somewhere in the memory (which is usually what you want when you declare a variable). It should be noted that for 'auto variables' new space will be allocated every time the scope of the variable is entered. (i.e. calling the function func() from within func() when func() declares an 'auto' variable will result in two different variables and each call to func() will only know about its own variable.
From this follows that auto variables declared at the global scope will be unique (since the scope is enterd only once).
Static variables however are always unique. Unique in the sense that space will only be allocated once. This is useful when func() calls func() and you want both function calls to operate on the same variable.
Extern variables are simply references to unique variables.
You use these when you want to access a global variable declared in a different file.
Given the files 1.c and 2.c it does not suffice to declare "int global;" in both files because space would be allocated twice and the name clash would result in a linking error.
Hence what you do is in one file to reserve space (using "int global;") and in the other file tell the linker to look for a variable of the name "global" in another file by writing "extern int global;".

Internal linkage with static keyword in C

I know static is an overloaded keyword in C. Here, I'm only interested in its use as a keyword to enforce internal linkage.
If you have a global variable declared in a .c file, what is the difference between using static and not using static? Either way, no other .c file has access to the variable, so the variable is basically "private" to the file, with or without the static keyword.
For example, if I have a file foo.c, and I declare a global variable:
int x = 5;
That variable x is only available to code inside foo.c (unless of course I declare it in some shared header file with the extern keyword). But if I don't declare it in a header file, what would be the difference if I were to type:
static int x = 5.
Either way, it seems x has internal linkage here. So I'm confused as to the purpose of static in this regard.
If you have a global variable declared in a .c file, what is the difference between using static and not using static? Either way, no other .c file has access to the variable [...]
A different file could declare x:
extern int x;
That would allow code referencing x to compile, and the linker would then happily link those references to any x it finds.
static prevents this by preventing x from being visible outside of its translation unit.
There is only one "namespace", so to speak, in C. Without the "static" keyword you are not protected from another file using the name "x" (even if you do not make it visible in your own library's header).
Try to link together several C files containing a non-static variable x (interleaving read and write accesses from functions in each file), and compare with the situation where these variables are declared static.

Static vs global

If I have a C file like below, what is the difference between i and j?
#include <stdio.h>
#include <stdlib.h>
static int i;
int j;
int main ()
{
//Some implementation
}
i has internal linkage so you can't use the name i in other source files (strictly translation units) to refer to the same object.
j has external linkage so you can use j to refer to this object if you declare it extern in another translation unit.
i is not visible outside the module; j is globally accessible.
That is, another module, which is linked to it, can do
extern int j;
and then be able to read and write the value in j. The same other module cannot access i, but could declare its own instance of it, even a global one—which is not visible to the first module.
The difference is that i has internal linkage, and j has external linkage. This means you can access j from other files that you link with, whereas i is only available in the file where it is declared.
i will have static linkage, i.e., the variable is accessible in the current file only.
j should be defined as extern, that is
extern int j;
in another header file (.h), and then it will have external linkage, and can be accessed across files.
Scope of static variable/function is within the same file despite you include the file as part of a different source file.
Scope of global variable is throughout the files in which it is included. To include the variable in a different source file, we use extern before the variable declaration. No memory is allocated again for the variable in this case.
extern is used to declare a C variable without defining it. extern keyword extends the visibility of the C variables and C functions. Since functions are visible through out the program by default, the use of extern is not needed in function declaration/definition. Its use is redundant.

Resources