Internal linkage with static keyword in C - 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.

Related

Why and where to use a global variable and a static global variable in C?

I have read about global and local variables and static keyword, but i dont know which is the difference between something like this:
int x; //Global variable
int main(){
//Code...
}
And this:
static int x; //Static Global variable
int main(){
//Code...
}
I know some properties of the static keyword, and i know why is useful for local variables, but i dont know which is the use for global variables
I have read that using static for global variables is used for accesing the variable only in the C file it is declared/defined, but, i mean, if we dont use extern we just cant access that global variable in other c files anyway
I think that a "static global" variable is used to prevent the use of the extern keyword in order to prevent the use of that variable in multiple C files, is that correct?
Thanks in advance!
"Global" is not a formal term, but it generally means "variable that can be accessed anywhere". Therefore global.
To dive into some formal terms:
The formal and correct term for a variable declared outside a function is declared at file scope.
What formally defines how a variable may be accessed in C is referred to as linkage.
A variable declared at file scope generally has external linkage and can be referred to from elsewhere with extern.
So the correct term to use for your first example is "file scope variable with external linkage".
Whenever we add the storage class specifier static to a declaration, we force the variable or function to instead get internal linkage. This means that it is only accessible from within the translation unit (the .c file and all .h files it includes) where it was declared.
It is the opposite of global, so saying "static global" doesn't make any sense. You cannot refer to such a variable with extern. Instead the correct term is "file scope variable with internal linkage".
The main purpose of static is indeed private encapsulation, since the internal linkage guarantees that the variable or function cannot be accessed by other .c files.
But static also at the same time gives static storage duration to a variable, meaning it is guaranteed to persist throughout the execution of the program and that it has some initialization rules guaranteed. Now as it happens, variables at file scope always gets static storage duration, static or not, so it isn't very relevant to your example. But as you earlier discovered, static storage duration does make a big difference for local variables, since their value will then be preserved throughout multiple function calls.
More details here: What does the static keyword do in C?
Yes, it is correct.
A global static variable can only be accessed in the file where it is created (file scope).

Global variables in a header file

I was just wondering if you declare a variable in a header file like this
const static int START = 0;
would that variable (START) be considered global?
If you define:
const static int START = 0;
at file scope, then START will have internal linkage and static duration due to static.
This means that each translation unit that includes the header will end up with a copy of the symbol and that each of them will live throughout the entire program.
Yes and no.
Lets say you add that definition into 'myvar.h' and then you include that header file into 'main.c' and 'other.c'
All functions in 'main.c' and 'other.c' will know about the defined variable --so in a way, it is global.
But in fact there will be two different variables with the same name. Changes made by functions in 'main.c' won't be visible by functions in 'other.c' and vice versa.
That's because static variables defined outside of functions are considered 'local to the compilation unit'.
On the other hand, if you just remove the 'static' keyword, the variable will be defined twice (once for each compilation unit in which the header file is included) and the linker will emit a 'duplicate symbol' error.

Just want to make sure I'm understanding what an external variable is

For our assignment we have to code a program in C, but it says not to use external variables in the program. Does this mean variables in other files brought into the main code, or am I unable to use variables in the same file if they're not in the same function? (ie: could I pass a value into a function as an argument and have it return a value that may have to do with a variable in that function and set the return value equal to something, or is that using external variables?)
I've Googled around but it's not exactly clear, and I want to make sure, as this is rather important.
Just to be sure, I'd make all my variables part of a function, and either pass them as parameters or return them from the functions.
There are at least two interpretations of external variables.
First off, we have the extern keyword, which basically symbolizes what you would call a global variable. It's a variable declared in multiple translation unit, but it only exists in one place in memory. It is initialized in a single file and all subsequent changes affect every scope the variable is used in:
//globals.cpp
int x = 1337;
//main.cpp
extern int x;
int main()
{
//x is 1337 here
return 0;
}
The second meaning could be a variable that is declared and defined in class scope, but not used as extern. However, you could consider it external to the methods.
//main.cpp
int x = 1337; //is this external?
//could be, remove it just to be safe
int main()
{
return 0;
}
Let's go with all the possible cases, because from your question I'm not too sure either:
There is extern as a keyword. In order to understand this, you need to understand compilation units. Basically, each file is a compilation unit - so each .c is compiled to a .o with the headers substituted in place. In each compilation unit, you forward declare symbols you expect to use - functions belonging to other compilation units, for example.
Now, if you declare a global variable in one .c file, it is global wrt that file, but does not exist as a symbol in any other file at all - the compiler will error because it doesn't know where that variable was declared.
(Of course, if you declare the variable in a header - it will exist in all of the objects the header is included in, and then the linker will sulk, because when it links all the objects up some of the symbols will have the same name).
To get around this, it is possible to define a variable with extern int x;, for example. This tells the compiler a) int x should be available to this compilation unit, b) int x is not in this compilation unit and c) the linker should check it exists somewhere in all the units you've put together to form a library or program.
Conceptually, you're doing this all the time with forward-declarations of functions. There's just no way to forward declare a variable. In fact, you can do this with functions too and not bother r.e shared headers, although this is not really a good idea.
The other case is that "external variables" mean something external to a certain scope or module you have. I would check your assignment very carefully and if in doubt ask - whoever set it should be able to explain to you exactly what they mean.
An external variable is a variable with external linkage.
A variable with external linkage is a variable defined at file scope without the static keyword.
int bla = 0; // external variable
static int blop = 1; // non-external variable
int main(void)
{
return bla
}
Note that a variable declared with the extern keyword doesn't necessarily have external linkage. Like const does not mean constant in C, extern does not mean external.
People often use the word external to say that a variable is actually declared in the current translation unit but is defined in another translation unit.

Is there a way to make a variable in C only accessible to the file in which it was declared?

Is there a way to make a variable in C only accessible to the file in which it was declared?
I am asking this because I remember reading somewhere that it's possible to do that, but I really can't remember how to do that. Is it possible, or am I just imagining?
Declare it as a static global.
static int foo;
int incrementfoo()
{
return ++foo;
}
Using the static keyword will give the global variable internal linkage, meaning that the name will not be visible to other translation units. However, note that this differs from what you asked for in that:
The name could still be accessed from other files included in the same translation unit (files included via the #include directive).
The variable can still be accessed by other translation units (modules) in your program if they can obtain its address, for example if there's a function in the same translation unit as your static variable which returns a pointer to it.
static is the word you are looking for
The static keyword does that; by contrast, the extern keyword can let you import other variables from other files.

Why won't extern link to a static variable?

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.

Resources