I have have two .c files (main.c and support.c). Support.c is compiled first and then main.c is compiled and linked with support.o. I have several non-static global variables in support.c.
How are those global variables from support.c stored? If main.c is multithreaded and has two threads calling the functions in support.c, are they sharing those globals, or do they each have their own copy?
A global variable is a global variable, and there's always just one, no matter in how many pieces you compile and link your program. If multiple threads access global data concurrently, you need to ensure the proper synchronization yourself.
The only way to get a separate copy of a global or block-static variable is to declare it _Thread_local, which was introduced in C11. Thread-local global variables are initialized when the thread is started, and deallocated when the thread is joined.
I think you might be confusing the usage of the static keyword when it applies to variables that exist top-level in C source (i.e. outside of any functions or methods), vs when you use static on variables within a function or keyword.
A variable declared top-level in the source code, outside of any functions, will be global unless you declare it as static. If it's static, it will be local only to that file. It controls the scope of the variable.
If you declare it static inside a function, it controls the lifetime of the variable. In this case, the variable will retain itself in memory even after the function call exits, resulting in its value persisting across multiple function calls.
If you declare a global variable (i.e. it's not static and is top-level in a source file), there will always only be one instance of it in memory. In other source files, you will have to declare it as extern so the linker knows to look for its memory location as defined in the object file for your other file, but there will be only one of it in memory.
Don't forget to declare the globals as volatile, or the compiler might not realized they can be modified by another thread and make unsafe optimizations.
volatile int g_example;
Related
my first question here.
can anyone explain to me the differnce between a global static variable (that is, defined above the functions and the "main" combined with "static") and a static variable that is defined inside a function?
as i understand it, they do the same - both enlarge the variable scope to the whole file, and both restrict it to the specific file. so... what am i missing?
plus another question (that came up when looking for a solution) - what is extern? i thought that defining a variable above the main would make it global (as in to other files too), but then i read someone explaining that in order to do so, i must add "extern" before the varible defining.
For variables defined outside of a function, the static keyword limits the variable to being referenced using its identifier from the file in which it is defined. Variables of this type will be assigned a fixed address by the linker (outside of the heap and stack), but will not be assigned a global symbol. If variables of this type are defined in multiple files with the same identifier, the linker should allocate separate memory in each case and should compile without warnings.
Variables defined with the static keyword inside of a function have similar memory allocation, but references to the variable using its identifier are limited to within that function. You could have multiple functions defining static variables with the same identifier and each will be allocated separately.
If an initializer is used for static variables, the variable is initialized once before the program begins executed and the initializer is evaluated at compile time. The initializer must evaluate to a constant expression in this case (no function calls or parameter or variable references).
The compiler will typically build each C file independent of all of the others in a program using symbols to define external dependencies, such as variables and functions located in other files. After each source file is compiled, the linker processes the compiler output to replace symbols with fixed addresses and build the entire program. In order to properly execute the build, the compiler must know the types and sizes of all external functions and variables. The type and number of parameters and return type of functions are typically shared in a header file using function prototype declarations. Function prototype declarations are implicitly identified as external by the compiler. The extern keyword is used to specify the type and size of variables declared in files outside of the file referencing the variable. Declaring a variable without the external keyword would cause it to be defined within the module where it is declared. If two variables with the same identifier are declared in multiple files without the static keyword, then the compiler will typically generate an error since the same global symbol is used multiple times in the program.
I have read a lot about extern variables but no one seems to address it appropriately. If I declare and define a variable in C, it gets memory assigned in that scope of the file. but at a later stage in multi-file modular project that variable is declared as an extern which should store the it in the Data segment to exhibit the global behavior intended with the extern functionality.
So I am trying to figure out how and when the memory is being allocated, i.e. the compile time and run time behavior of the extern variable.
One of the compilation units has to define the variable as a global variable. When compiling this file, memory is allocated for the variable in the data segment, similar to file scope variables. The difference is that the variable is registered in the linkage table so that other object files can find it.
All the other compilation units declare it using the extern keyword. This prevents them from allocating memory for the variable, and arranges for the linker to find the external variable.
When you link all the object files together, the linker finds all the object files that have the external reference to the variable, and connects that link to the memory that was allocated in the first object file.
#include<stdio.h>
static int a=5;
main()
{
static int a=15;
printf("%d\n",a);
}
So, how are both variables a stored in internal memory?
How are global and local variables with the same variable names stored internally in memory?
#include<stdio.h>
static int a=5;
int main()
{
printf("%p\n",(void *)&a);
static int a=15;
printf("%p\n",(void *)&a);
return 0;
}
Output for the upper program is
0x564e6b67a030
0x564e6b67a034
So you can see that both are stored in different addresses. As one is a global variable and other is local.
The names are only of interest to the human reader and the compiler/linker translating that code to machine executable code. The final object code resolves these to addresses and the names no longer exist.
The compiler distinguishes these the same way you do - by scope; when two identical symbols in the same namespace are in scope simultaneously, the symbol with the most restrictive scope is visible (i.e. may be accessed via the name).
For symbols with external linkage (in your example there are none other then main), the compiler retains the symbol name in order to resolve links between separately compiled modules. In the fully linked executable the symbol names cease to exist (except in debug build symbol meta-data).
The thing is the scope don't let them mess up. The first one has file scope and the other has block scope. (They are different variables - they are stored in separate memories.)
When you use it in the block - compiler checks whether this reference is resolved by anything in the same block. It gets one. And done.
And in case it is in some other function - if it doesn't find anything named a - the search ends in file scope where it finds the name a. That is where the story ends.
Both being static their storage duration is same. They live till the program exists. But their scope is different. If the scope was same too - compiler would have shown you error message.
Here if you compile with -Wshadow option - it will warn you about shadowing a variable. You shadowed the outer a with the inner on that block. That's it.
The facetious answer is that they are stored in different places.
Remember that the names of variables do not (normally) form part of the compiled program, so the compiler just follows the normal rules of variable shadowing. So in your case your print function (that's not a standard C function by the way - did you mean printf?) outputs the a declared in main. The fact that you've used the same name will not bother the compiler at all.
Finally C provides no way of accessing the global scoped a once the other declaration is encountered in main as it's static. (It is wasn't static you could use extern.) See How can I access a shadowed global variable in C?
I wonder about the use of the static keyword as scope limiting for variables in a file, in C.
The standard way to build a C program as I see it is to:
have a bunch of c files defining functions and variables, possibly scope limited with static.
have a bunch of h files declaring the functions and possibly variables of the corresponding c file, for other c files to use. Private functions and variables are not published in the h file.
every c file is compiled separately to an o file.
all o files are linked together to an application file.
I see two reasons for declaring a gobal as static, if the variable is not published in the h file anyway:
one is for readability. Inform future readers including myself that a variable is not accessed in any other file.
the second is to prevent another c file from redeclaring the variable as extern. I suppose that the linker would dislike a variable being both extern and static. (I dislike the idea of a file redeclaring a variable owned by someone else as extern, is it ok practice?)
Any other reason?
Same goes for static functions. If the prototype is not published in the h file, other files may not use the function anyway, so why define it static at all?
I can see the same two reasons, but no more.
When you talk about informing other readers, consider the compiler itself as a reader. If a variable is declared static, that can affect the degree to which optimizations kick in.
Redefining a static variable as extern is impossible, but the compiler will (as usual) give you enough rope to hang yourself.
If I write static int foo; in one file and int foo; in another, they are considered different variables, despite having the same name and type - the compiler will not complain but you will probably get very confused later trying to read and/or debug the code. (If I write extern int foo; in the second case, that will fail to link unless I declare a non-static int foo; somewhere else.)
Global variables rarely appear in header files, but when they do they should be declared extern. If not, depending on your compiler, you risk that every source file which includes that header will declare its own copy of the variable: at best this will cause a link failure (multiply-defined symbol) and at worst several confusing cases of overshadowing.
By declaring a variable static on file level (static within function has a different meaning) you forbid other units to access it, e.g. if you try to the variable use inside another unit (declared with extern), linker won't find this symbol.
When you declare a static function the call to the function is a "near call" and in theory it performs better than a "far call". You can google for more information. This is what I found with a simple google search.
If a global variable is declared static, the compiler can sometimes make better optimizations than if it were not. Because the compiler knows that the variable cannot be accessed from other source files, it can make better deductions about what your code is doing (such as "this function does not modify this variable"), which can sometimes cause it to generate faster code. Very few compilers/linkers can make these sorts of optimizations across different translation units.
If you declare a variable foo in file a.c without making it static, and a variable foo in file b.c without making it static, both are automatically extern which means the linker may complain if you initialise both, and assign the same memory location if it doesn't complain. Expect fun debugging your code.
If you write a function foo () in file a.c without making it static, and a function foo () in file b.c without making it static, the linker may complain, but if it doesn't, all calls to foo () will call the same function. Expect fun debugging your code.
My favorite usage of static is being able to store methods that I wont have to Inject or create an object to use, the way I see it is, Private Static Methods are always useful, where public static you have to put some more time in thinking of what it is your doing to avoid what crazyscot defined as, getting your self too much rope and accidentally hanging ones self!
I like to keep a folder for Helper classes for most of my projects that mainly consist of static methods to do things quickly and efficiently on the fly, no objects needed!
I understand what static does, but not why we use it. Is it just for keeping the abstraction layer?
There are a few reasons to use static in C.
When used with functions, yes the intention is for creating abstraction. The original term for the scope of a C source code file was "translation unit." The static functions may only be reached from within the same translation unit. These static functions are similar to private methods in C++, liberally interpreted (in that analogy, a translation unit defines a class).
Static data at a global level is also not accessible from outside the translation unit, and this is also used for creating an abstraction. Additionally, all static data is initialized to zero, so static may be used to control initialization.
Static at the local ("automatic") variable level is used to abstract the implementation of the function which maintains state across calls, but avoids using a variable at translation unit scope. Again, the variables are initialized to zero due to static qualification.
The keyword static has several uses; Outside of a function it simply limits the visibility of a function or variable to the compilation unit (.c file) the function or variable occurs in. That way the function or variable doesn't become global. This is a good thing, it promotes a kind of "need to know" principle (don't expose things that don't need to be exposed). Static variables of this type are zero initialized, but of course global variables are also zero initialized, so the static keyword is not responsible for zero initialization per se.
Variables can also be declared static inside a function. This feature means the variable is not automatic, i.e. allocated and freed on the stack with each invocation of the function. Instead the variable is allocated in the static data area, it is initialized to zero and persists for the life of the program. If the function modifies it during one invocation, the new modified value will be available at the next invocation. This sounds like a good thing, but there are good reasons "auto" is the default, and "static" variables within functions should be used sparingly. Briefly, auto variables are more memory efficient, and are essential if you want your function to be thread safe.
static is used as both a storage class specifier and a linkage specifier. As a linkage specifier it restricts the scope of an otherwise global variable or function to a single compilation unit. This allows, for example a compilation unit to have variables and functions with the same identifier names as other compilation units but without causing a clash, since such identifiers are 'hidden' from the linker. This is useful if you are creating a library for example and need internal 'helper' functions that must not cause a conflict with user code.
As a storage class specifier applied to a local variable, it has different semantics entirely, but your question seems to imply that you are referring to static linkage.
Static functions in C
In C, functions are global by default. The “static” keyword before a function name makes it static. For example, below function fun() is static.
static int fun(void)
{
printf("I am a static function ");
}
Unlike global functions in C, access to static functions is restricted to the file where they are declared. Therefore, when we want to restrict access to functions, we make them static. Another reason for making functions static can be reuse of the same function name in other files.
For example, if we store following program in one file file1.c
/* Inside file1.c */
static void fun1(void)
{
puts("fun1 called");
}
And store following program in another file file2.c
/* Iinside file2.c */
int main(void)
{
fun1();
getchar();
return 0;
}
Now, if we compile the above code with command gcc file2.c file1.c, we get the error undefined reference to fun1. This is because fun1 is declared static in file1.c and cannot be used in file2.c. See also the explanation here, where the codes come from.