Why Storage-Class Specifiers are used to determine two independent properties? - c

From Storage-class specifiers:
The storage-class specifiers determine two independent properties of the names they declare: storage duration and linkage.
So, for example, when static keyword is used on global variables and functions (who's storage class is static anyway) it sets their linkage to Internal-linkage. When used on variables inside functions (which have no linkage) - it sets their storage class to static.
My question is: why is the same specifier used for both things?

The reason is mostly historical: linkage came into the design of C language as an afterthought. In the early versions you could redeclare global variables as many times as you wish, and linker would merge all these declarations for you:
Ritchie's original intention had been to model C's rules on FORTRAN COMMON declarations, on the theory that any machine that could handle FORTRAN would be ready for C. In the common-block model, a public variable may be declared multiple times; identical declarations are merged by the linker. (source)
The current rule of a single declaration came later, along with extern keyword. At that point there was a body of C code significant enough to make backward compatibility important. That is probably the reason why language designers refrained from introducing a new keyword for handling linkage, reusing static instead.

Related

Whether Global Variables in C, static or extern?

I just started learning C programming.
In some of the books and web articles, I could find that any Global Variable in C by default corresponds to static storage class but has external linkage.
Does this mean it is partially static and partially extern? Because as per my understanding any global variable with static storage class specifier has internal linkage only and can be accessed within the same file.
P.S: I referred this question Global variables in C are static or not? , but could not get really whether Global variables are static or extern by default in C.
Global Variable in C by default corresponds to static storage class but has external linkage. Does this mean it is partially static and partially extern?
The English word “static” has muddled and multiple meanings in C, and, yes, the default for a variable declared outside a function is to have static storage duration and external linkage.
Because there are multiple concepts here and some mixed use of word meanings, we should clarify some terminology and formatting:
Use code style to refer to specific text in source code, such as the keyword static. When speaking of static storage duration or external linkage, “static” and “external” are mere English adjectives and should not be in code style.
“Global” means visible throughout an entire program. The C standard does not use this word for this purpose. It uses “external” to refer to things that are outside of (external to) any function. (But it also uses “external” for other purposes.) A global variable could not have internal linkage, because it would not be visible throughout the entire program.
A variable consists of an object (memory reserved for representing the value) and an identifier (the name). Storage duration is a property of the object. Linkage is a property of the identifier.
The English word “static” generally means unchanging. The C standard uses this word and the keyword static in multiple ways:
Static storage duration means the memory for an object is reserved throughout all of program execution.
Using the static keyword in a declaration, other than as below, both gives an object static storage duration and, in a declaration outside a function, gives the identifier internal linkage.
Using the static keyword inside subscript markers in a parameter declaration, as in void foo(int a[static 3]), indicates that the parameter points to at least the stated number of elements.
Static assertions, using _Static_assert, provide compile-time tests (which can help detect bugs or ensure a program is being compiled with expected settings).
These multiple uses are unfortunate and are due at least partly to the history of how the C language was developed.
Whenever you don't intend to use a variable declared in one file in a Different file the you should use static keyword before the declaration
file1.c:
static int number = 63; // this variable is used only in this file
...
file2.c:
float brightness = 0.5; // is needed in some Other file;
...
file3.c:
extern float brightness; // use external declaration to use it here
...
When ever possible, you should use the static variables.
If you want to use two global variables in two different translation units (c files) then your compiler will throw an error saying that the variable is already declared elsewhere.
Using static will make it hidden for other translation units.
You mix up static and static storage duration.
Storage duration and linkage are different terms. There is nothing in C called "global", though the term is often sloppily used for any variable declared at file scope - that is: outside any function. More correct use of the term "global" would be that the variable has external linkage, meaning it may be referred to anywhere in the whole project.
All variables declared at file scope have static storage duration. This dictates how such variables are initialized and that they persist throughout the whole exeuction of the program (practically, it likely also means that the variable ends up in .data or .bss segments of the implementation).
A variable declared at file scope but without any storage class specifier (neither static nor extern) has external linkage, but it still got static storage duration. From 6.2.4:
If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external.
But if you add a storage class specifier to a file scope variable, you specify both storage duration and linkage. 6.2.4/3:
If the declaration of a file scope identifier for an object or a function contains the storage-class specifier static, the identifier has internal linkage.
And as you say, a variable with internal linkage can only be referred to from the same file (strictly speaking same "translation unit").
There's some subtle difference here in case you add static to a local variable - it then specifies storage duration but not linkage. The whole term linkage is rather confusing - simply put the purpose of the term is to dictate when two variables with the same name refer to the same object or different ones. This is mostly a concern for those making compilers/linkers as well as for spaghetti programmers. Avoid belonging to the latter category by following the advise below.
Beginners need not worry about any of the above.
Rules of thumb for beginners:
Never declare variables outside functions unless they are static.
Never declare variables in header files.
Never use extern.
Use static in front of functions if they aren't meant to be called from other files.
This will get you very far, and the rare cases where you actually need to share variables between different files is another story/advanced topic.

different types of Static in C

I know there are three types of static declerations in C:
1: Constant - constant static variable, ex: static const int i = 5;
2: Changable - just a normal static variable, ex: static int hi = 10;
Here is my question
There is another form of static which takes the form of "code". What does that mean and can you give me an example?
Thank you!
EDIT:
Are static/const variables stored on the stack/heap?
Maybe you are talking about a static function ?
This is a specific use of the word "static", which is entirely different from a static variable.
When you declare a function "static", that means it cannot be linked from another source file. It is typically used to keep some functions "private".
[Edit] Note that, in theory, the function code could still be accessed from another source file using pointers, but that's not quite the normal way (and certainly not the easiest) to access a function. Thanks to Eric Postpischil for pointing that out.
It's unfortunate that the same word "static" is used in the C standard to mean two different things, depending on being used for functions or variables.
[edit] : It's a different question, but anyway : in the case of static variables, they are neither allocated in the heap nor the stack. They are, well, static, which means they are allocated in a static space, directly allocated by the compiler at startup. Stack is for internal functions variables, and heap is for malloc()/free().
This link should answer your question.
It is however worth noting that unless you have sufficient knowledge of the C compilation process this will be of questionable value.
A good reference for GCC can be found here.
I believable you're asking about static functions.. So..
Static functions
By default, functions in C are extern, meaning that the function can be used in any other file of the same project (and the same code of course).
If you don't like this situation and you want to limit the function to the file in which it's defined, you make it static.
The keyword static is used in several different ways in C. (There's a joke that any new version of the ISO C standard is required to invent a new meaning for static.)
Quick summary: The static keyword on a block scope definition gives the entity static storage duration; at file scope, where definitions already have static storage duration, it instead gives them internal linkage.
An object may have any of several storage durations. An object with "automatic" storage duration exists at run time only during the execution of the enclosing block. An object with "static" storage duration exists during the entire execution of the program. (There are also "allocated" and, new in C11, "temporary" storage durations, which I won't get into.)
Any definition of an identifier also has a "linkage", which can be external, internal, or none. Linkage controls whether an identifier is usable across translation units (basically source files, but #included files are not separate translation units). Linkage, as the name implies, has to do with the linker. You can use the same identifier with internal linkage in two different source files, and it will refer to two different entities. But if an identifier has external linkage, it should be defined only once, and can be declared (typically with extern) in multiple source files; all those declarations will refer to the same entity.
If you define an object (variable) at block scope, (i.e., inside a function body), it has automatic storage duration (and no linkage) by default. Adding the keyword static gives it static storage duration, so it exists and retains its value across calls to the function. (It doesn't affect the identifier's visibility).
If you define an object at file scope (i.e., outside any function body), it has static storage duration and external linkage by default. Adding the keyword static to the definition doesn't affect its storage duration, but it changes its linkage from external to internal, hiding the name from other translation units. Functions don't have storage duration (their code exists as long as the program is running), but static affects their linkage the same way, changing it from external to internal.
(C99 added another meaning for static, for function parameters of array type, which has nothing to do with the other uses.)
I think it's worth to clarify what we're talking about and try to use the correct wording.
The const qualifier has nothing to do with the static keyword.
Technically, the static keyword appears in declarations and it's usually a storage-class specifier, but from C99 it can also be in array declarators, though this is quite unusual.
When it's a storage-class specifier, just like in the declarations you've posted, it affects the linkage (visibility between files) of the identifier and the storage duration (lifetime) of the identified object, but not the scope of the identifier.
6.2.2 Linkages of identifiers
[...] Within one translation unit, each declaration of an identifier with internal linkage denotes the same object or function. [...]
If the declaration of a file scope identifier for an object or a function contains the storage-class specifier static, the identifier has internal linkage.30)
30) A function declaration can contain the storage-class specifier static only if it is at file scope; see 6.7.1.
Therefore, the identifier can only be seen in the translation unit (i.e., a source file after the preprocessing) where it's declared, whether it's an object or a function (maybe that's what you were looking for). So you can use to declare "private" functions to be used in just one file.
static void foo(void)
{
// ...
}
The static keyword it's also used with the inline function specifier, which has a particular linkage semantics: https://stackoverflow.com/a/216546/1202636
Obviusly when we are not at file scope but in a more restricted one (static declarations inside functions) the linkage question becomes irrelevant since such an identifier has no linkage at all.
6.2.4 Storage durations of objects
An object whose identifier is declared [...] either with external or internal linkage or with the storage-class specifier static, has static storage duration. Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup.
This one only applies to object identifiers and it affects the lifetime of the object, for example letting a variable retains its value between calls, and its initialization.
(just to say it, such an object is also initialized with a default value)
As I said, there's a less common use of the static keyword: it can be use in array declarators inside function prototypes, to tell the compiler that an array given as parameter contains at least n elements. This is a (modified) example from the standard:
void f(double a[static 3][5]);
The declaration specifies that the argument corresponding to a in any call to f must be a non-null pointer to the first of at least three arrays of 5 doubles, which the others do not.
.
Are static/const variables stored on the stack/heap?
Again, the constness has nothing to do with the place where an object is stored. The standard doesn't say anything about that place, there's usually a dedicated area but this is a different and already answered question: where are static buffers allocated?
Are static/const variables stored on the stack/heap?
Well, no, they are part of the "global" space.
Stack and Heap are for "dynamic" memory allocation, not static !

Why and when to use static structures in C programming?

I have seen static structure declarations quite often in a driver code I have been asked to modify.
I tried looking for information as to why structs are declared static and the motivation of doing so.
Can anyone of you please help me understand this?
The static keyword in C has several effects, depending on the context it's applied to.
when applied to a variable declared inside a function, the value of that variable will be preserved between function calls.
when applied to a variable declared outside a function, or to a function, the visibility of that variable or function is limited to the "translation unit" it's declared in - ie the file itself. For variables this boils down to a kind of "locally visible global variable".
Both usages are pretty common in relatively low-level code like drivers.
The former, and the latter when applied to variables, allow functions to retain a notion of state between calls, which can be very useful, but this can also cause all kinds of nasty problems when the code is being used in any context where it is being used concurrently, either by multiple threads or by multiple callers. If you cannot guarantee that the code will strictly be called in sequence by one "user", you can pass a kind of "context" structure that's being maintained by the caller on each call.
The latter, applied to functions, allows a programmer to make the function invisible from outside of the module, and it MAY be somewhat faster with some compilers for certain architectures because the compiler knows it doesn't have to make the variable/function available outside the module - allowing the function to be inlined for example.
Something that apparently all other answers seem to miss: static is and specifies also a storage duration for an object, along with automatic (local variables) and allocated (memory returned by malloc and friends).
Objects with static storage duration are initialized before main() starts, either with the initializer specified, or, if none was given, as if 0 had been assigned to it (for structs and arrays this goes for each member and recursively).
The second property static sets for an identifier, is its linkage, which is a concept used at link time and tells the linker which identifiers refer to the same object. The static keyword makes an identifier have internal linkage, which means it cannot refer to identifiers of the same name in another translation unit.
And to be pedantic about all the sloppy answers I've read before: a static variable can not be referenced everyhere in the file it is declared. Its scope is only from its declaration (which can be between function definitions) to the end of the source file--or even smaller, to the end of the enclosing block.
struct variable
For a struct variable like static struct S s;, this has been widely discussed at: What does "static" mean in C?
struct definition: no effect:
static struct S { int i; int j; };
is the exact same as:
struct S { int i; int j; };
so never use it. GCC 4.8 raises a warning if you do it.
This is because struct definitions have no storage, and do no generate symbols in object files like variables and functions. Just try compiling and decompiling:
struct S { int i; int j; };
int i;
with:
gcc -c main.c
nm main.o
and you will see that there is no S symbol, but there is an i symbol.
The compiler simply uses definitions to calculate the offset of fields at compile time.
This is struct definitions are usually included in headers: they won't generate multiple separate data, even if included multiple times.
The same goes for enum.
C++ struct definition: deprecated in C++11
C++11 N3337 standard draft Annex C 7.1.1:
Change: In C ++, the static or extern specifiers can only be applied to names of objects or functions
Using these specifiers with type declarations is illegal in C ++. In C, these specifiers are ignored when used
on type declarations.
See also: https://stackoverflow.com/a/31201984/895245
If you declare a variable as being static, it is visible only in that translation unit (if globally declared) or retains its value from call to call (if declared inside a function).
In your case I guess it is the first case. In that case, probably the programmer didn't want the structure to be visible from other files.
The static modifier for the struct limits the scope of visibility of the structure to the current translation unit (i.e. the file).
NOTE: This answer assumes (as other responders have indicated) that your declaration is not within a function.

How are global static/non-static variables mangled in c?

I can imagine static variables var inside a function func to be named like var#func,
what about global static and non-static variables?
Compilers don't need to uniquely name things with internal linkage, like static variables and functions. You can't access static objects outside the translation unit, so the linker doesn't need to get a name for them.
Global variables with external linkage don't usually have much mangling or decoration applied to their names, and it's often exactly the same that is applied to functions. A single leading underscore is not terribly uncommon.
Adding on that since the information given here is at least incomplete. Most compilers will create "local" symbol for static variables, and yes, since the naming of static variables in function scope is not unique, they have to mangle the names. gcc, e.g, does that by appending a dot and a unique number to the name. Since the dot is not part of any valid identifier, this makes sure that there is no name clash.
Things become obscure when the compiler supports universal characters in identifiers. Depending on the environment, the compiler has to mangle such identifiers, since e.g the loader might not support such characters in the symbol table.
icc chooses something like replacing such a character by _uXXXX where XXXX is the hex representation of the character. In that case (icc) this results in two subtle compiler bugs. First, this mangling uses valid identifiers that the user is allowed to use, so they may clash for global symbols with identifiers from the same compilation unit or even from other units. Second, icc even mixes up its own internal naming and reserves only space for one static variable and if they are eg also declared volatile completely runs into the wild.

Is extern keyword for function necessary at all in C?

It appears to me that even if I refer to a function in another file with out extern declaration, gcc can still compile that unit. So I am wondering whether the extern declaration is necessary anywhere for function? I know that you need extern for variables.
functions have extern storage class specifier by default (unless they are explicitly defined as static)
extern Storage Class Specifier
If the declaration describes a function or appears outside a function and describes an object with external linkage, the keyword extern is optional. If you do not specify a storage class specifier, the function is assumed to have external linkage.
....
It is an error to include a declaration for the same function with the storage class specifier static before the declaration with no storage class specifier because of the incompatible declarations. Including the extern storage class specifier on the original declaration is valid and the function has internal linkage.
It's not necessary, but I prefer it in headers to reinforce the idea that this function is defined somewhere else.
To me, this:
int func(int i);
is a forward declaration of a function that will be needed later, while this:
extern int func(int i);
is a declaration of a function that will be used here, but defined elsewhere.
The two lines are functionally identical, but I use the extern keyword to document the difference, and for consistency with regular variables (where the difference is important, and has exactly that meaning).
You do not necessarily "need" extern for variables.
When C was invented Unix linkers were also written, and they advanced the art in unheralded but clever ways. One contribution was defining all symbols as small "common blocks". This allowed a single syntax for declarations with no required specification of which module was allocating the space. (Only one module could actually initialize the object, but no one was required to.)
There are really three considerations.
Forward declarations for prototypes. (Optional, because legacy C has to compile without them.)
Extern declarations for non-function objects (variables) in all files except one. (Needed only on non-Unix systems that also have crummy linkers. Hopefully this is rare these days.)
For functions, extern is already the assumption if no function body is present to form a definition.
As far as I remember the standard, all function declarations are considered as "extern" by default, so there is no need to specify it explicitly.
That doesn't make this keyword useless since it can also be used with variables (and it that case - it's the only solution to solve linkage problems). But with the functions - yes, it's optional.
A little more verbose answer is that it allows you to use variables compiled in another source code file, but doesn't reserve memory for the variable. So, to utilise extern, you have to have a source code file or a library unit that contains memory space for the variable on the top level (not within functions). Now, you can refer to that variable by defining an extern variable of the same name in your other source code files.
In general, the use of extern definition should be avoided. They lead easily to unmanagable code and errors that hard to locate. Of course, there are examples where other solutions would be impractical, but they are rare. For example, stdin and stdout are macros that are mapped to an extern array variable of type FILE* in stdin.h; memory space for this array is in a standard C-library unit.

Resources