In our project, we have pretty big C file of around 50K lines, written in 90's.
I wanted to split the file based on the functionality. But, all the functions in this file are declared as static. So, file scoped. If I split the file, then the function in file1 cannot call function in file2 and vice-versa.
But, My TL feels like that there could be memory optimization by using static functions.
I wrote some sample code to see if the stacks are different for different threads.
It seemed like it was. Could someone please enlighten me the difference between static function and a normal one other an file scope?
In C, while defining a function, the static keyword has the following 2 major consequences :
Prevents the function name from being exported (i.e. function does NOT have external linkage). Thus, preventing linkage / direct calls from other parts of the code.
As the function is clearly marked private to the file, the compiler is in a better position to generate a complete call-graph for the function. This may result in the compiler deciding to automatically in-line the function for better performance.
All functions are implicitly declared as extern, which means they're visible across translation units. But when we use static it restricts visibility of the function to the translation unit in which it's defined. So we can say Functions that are visible only to other functions in the same file are known as static functions.
The most important difference is you cannot call the static function in any other files. i think so ,yeah?
Related
I have heard that, when you have just 1 (main.c) file (or use a "unity build"), there are benefits to be had if you make all your functions static.
I am kind of confused why this (allegedly) isn't optimized by default, since it's not probable that you will include main.c into another file where you will use one of its functions.
I would like to know the benefits and dangers of doing this before implementing it.
Example:
main.c
static int my_func(void){ /*stuff*/ }
int main(void) {
my_func();
return 0;
}
You have various chunks of wisdom in the comments, assembled here into a Community Wiki answer.
Jonathan Leffler noted:
The primary benefit of static functions is that the compiler can (and will) aggressively inline them when it knows there is no other code that can call the function. I've had error messages from four levels of inlined function calls (three qualifying “inlined from” lines) on occasion. It's staggering what a compiler will do!
and:
FWIW: my rule of thumb is that every function should be static until it is known that it will be called from code in another file. When it is known that it will be used elsewhere, it should be declared in a header file that is included both where the function is defined and where it is used. (Similar rules apply to file scope variables — aka 'global variables'; they should be static until there's a proven need for them elsewhere, and then they should be declared in a header too.)
The main() function is always called from the startup code, so it is never static. Any function defined in the same file as an unconditionally compiled main() function cannot be reused by other programs. (Library code might contain a conditionally compiled test program for the library function(s) defined in the source file — most of my library code has #ifdef TEST / …test program… / #endif at the end.)
Eirc Postpischil generalized on that:
General rule: Anytime you can write code that says the use of something is limited, do it. Value will not be modified? Make it const. Name only needs to be used in a certain section? Declare it in the innermost enclosing scope. Name does not need to be linked externally? Make it static. Every limitation both shrinks the window for a bug to be created and may remove complications that interfere with optimization.
I've seen a couple of times that the prototype declaration of a function in the header was literally repeated in the c-file.
It is possible to declare a function more than one time in C - but what sense does it make? Is it just for better readability or is there some deeper insight which I am missing?
It is possible. It doesn't make any sense.
But it does not cause any harm either. You can declare a function as many times as you like, but each such declaration must be identical to the others. So it is pointless to do so. As someone suggested, maybe it is a copy/paste error.
You can only have one function definition though, which should always be in the c file.
This is how you should do it:
Function declarations which is part of the caller's interface should be in the h file, and there only.
Function declarations of local (private) functions that are only available from inside the c file itself, should be in the c file, and there only. Such functions should be declared and defined as static.
Duplicate function declarations serve no useful semantic purpose, but they may arise for historical reasons, because of local coding conventions, or for some other reason.
For example, it may be a local coding convention that every function in each source file is prototyped at the beginning of that file. That has some minor practical utility, such as serving as a manifest of the functions defined in each file, and making the functions inside each file able to ignore any concern about whether other functions in the same file are declared in a header.
Additionally, multiple declarations of the same function or object don't necessarily have to be identical, they only need to be compatible. Under some circumstances it may makes sense to provide a less specific prototype in a header and a more specific one in the source file containing the function definition (which itself serves as yet another declaration).
So I'm working on a "quick and dirty" profiler for firmware- I just need to know how long some functions take. Merely printing the time it takes every time will skew the results, as logging is expensive- so I am saving a bunch of results to an array and dumping that after some time.
When working in one compilation unit (one source file), I just had a bunch of static arrays storing the results. Now I need to do this across several files. I could "copy paste" the code, but that would be just ugly (Bear with me). If I put timing code in a seperate compilation unit, make static variables, and provide accessor functions in the header file, I will be incurring the overhead of function calls every time i want to access those static variables.
Is it possible to access static variables of a compilation unit directly?
I've always tried to encapsulate data, and not use global variables, but this situation calls for it simply due to speed concerns.
I hope this makes sense! Thank you!
EDIT: Alright, so it appears what I'm asking is impossible- do any of you see alternatives that essentially allow me to directly access data of another compilation unit?
EDIT2: Thank you for the answers Pablo and Jonathan. I ended up accepting Pablo's because I didn't have clear place to get the pointer to the static data (as per Jonathan) in my situation. Thanks again!
No, it's not possible to access static variables of a compilation unit from another one. static keyword precisely prevents that from happening.
If you need to access globals of one compilation unit from another, you can do:
file1.c:
int var_from_file1 = 10;
file2.c:
extern int var_from_file1;
// you can access var_from_file1 here
If you can remove the static keyword from your declarations, you should be fine. I understand that changing existing source code is not always an option (I.E. dealing with existing legacy compiled code).
To get at the static variables in a compilation unit C1 from another unit C2, some function in C1 must make pointers to the variables available to C2, or some non-static variable must contain a pointer to the static variables.
So, you could package the 'static variables' into a single structure, and then write a function that returns a pointer to that structure; you can call that function to gain access to the static variables.
Similar rules apply to static functions; if some function (or non-static variable) in the file makes the pointers to the functions available, then the static functions can be called indirectly from outside the file.
If access via pointers doesn't count as directly, then you are snookered; static hides and you can't unhide except by removing the keyword static from the variables when the module is compiled - maybe via the C preprocessor. Beware name clashes.
I have a little project in which I named two same name function in two different source file, but while I building the project, the compiler failed with 'func_name already defined in filename.obj'.
Why could not I have two functions with the same name in two different source files? I thought the function should be local to the source file only if when we declared it in the header file will it become global.
And except for changing the filename, are there any other elegant solution to duplicated function name in the C programming language?
In C, a function has global scope by default. To restrict its scope, use the static keyword to make it private to a the module.
The role of the header file is just to publicize the function along with its signature to other modules.
All global names must (with some caveats) be unique. This makes sense because that name is what is used by the linker to connect a function call to implementation of the function itself.
Names with static and local scope need only be unique within their scope.
Whether some thing is declared in header file or in source file makes absolutely no difference for the compiler. In fact, the compiler proper knows absolutely nothing about any "header files", since header files are embedded into source files by so called preprocessor, which does its work before the compiler proper. By the time the source files (with embedded header files) get to the actual compiler, there's no way to tell what was there originally and what was inserted from header files. The source file with all the header files embedded into it is called translation unit. I.e. the compiler proper works with translation units, not with some "source" or "header" files.
In C language all objects and functions declared at file scope have external linkage by default, which means that they are global, unique for the entire program. So, you thought incorrectly. Functions are not local to one source file only.
If you want to make a function (or an object) local to a single translation unit, you have to take some explicit steps. You have to declare it as static. Declaring it as static will give it internal linkage, which essentially means that it becomes internal to its translation unit.
Declaring your functions static will only work if both of them really have to be local to their own translation units. If this is not the case, i.e. if at least one of the functions should be a globally accessible (linkable) function, then you have no other choice but to rename one of functions.
Why could not I have two function with the same name in two differenct source file?
Because the linker needs to know which is meant when you reference it.
Imagine that a.h and b.h both declare my_function(). The compiler generates code for both. Now, imagine that c.c calls my_function() - how does the linker know which of the two versions of the function should be called?
Declare the function static to make it local to the file. In C, every identifier name must be unique.
The elegant solution is namespaces introduced in C++. The solution, if there are few calls to func_name is take one, rename it and recompile.
Something hackerous but quick solution might be this:
//In one of the two source files and any file that calls it
//if your functions is something like this
//void func_name(int) { ... }
//Add the following line
#define func_name SOME_UNIQUE_FUNC_NAME
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!