Can the main() function be declared static in a C program? If so then what is the use of it?
Is it possible if I use assembly code and call the static main() function myself (consider embedded programs)?
No. The C spec actually says somewhere in it (I read the spec, believe it or not) that the main function cannot be static.
The reason for this is that static means "don't let anything outside this source file use this object". The benefit is that it protects against name collisions in C when you go to link (it would be bad bad bad if you had two globals both named "is_initialized" in different files... they'd get silently merged, unless you made them static). It also allows the compiler to perform certain optimizations that it wouldn't be able to otherwise. These two reasons are why static is a nice thing to have.
Since you can't access static functions from outside the file, how would the OS be able to access the main function to start your program? That's why main can't be static.
Some compilers treat "main" specially and might silently ignore you when you declare it static.
Edit: Looks like I was wrong about that the spec says main can't be static, but it does say it can't be inline in a hosted environment (if you have to ask what "hosted environment" means, then you're in one). But on OS X and Linux, if you declare main static, then you'll get a link error because the linker can't find the definition of "main".
You could have a static function called main() in a source file, and it would probably compile, but it would not be the main() function because it would be invisible to the linker when the start-up code (crt0.o on many (older) Unix systems) calls main().
Given the code:
static int main(int argc, char **argv)
{
return(argv + argc);
}
extern int x(int argc, char **argv)
{
return(main(argc, argv));
}
GCC with -Wall helpfully says:
warning: 'main' is normally a non-static function
Yes, it can be done. No, it is normally a mistake - and it is not the main() function.
No you cannot do it. If you will do it you will be unable to compile your program. Because static function is only visible within the same file, so the linker will no be able to find it and make a call of it.
As others have said, no it can't. And that goes double if you ever intend to port your code to C++, as the C++ Standard specifies that main() need not actually be a function.
C has two meanings for 'static'...
static for a local variable means it can be used globally.
static for a global variable means is can only be used in the current file.
static for functions has the exact same impact as denoting a global variable as static ... the static function IS ONLY VISIBLE IN THE CURRENT FILE ...
Thus main can NEVER be static, because it would not be able to serve as the primary entry point for the program.
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.
Let's say I'm writing a library of functions, and each function makes use of a global array to perform its duties. I don't want to expose that array to non library code, so I declare it as static like so:
library.h:
void function1();
void function2();
library.c:
#include "library.h"
static int arr[ARBITRARY_SIZE];
void function1() {...} // both of these
void function2() {...} // make use arr
If I now want to use this library in my code, I would #include "library.c" at the top of my code.
If I understand correctly, #include simply copies and pastes in place the contents of the #includeed file. If this is the case, the user's code would itself contain the static definition of arr. Given that, how would I, as the author of the library, protect my library variables? If this is not the case, please correct me about what #include does!
static keyword doesn't protect the memory used by a variable, you can pass out of a function (with visibility of it) a reference to the variable so the variable is accessible out of the block where it is defined. Then the calling code can use that reference to modify it as desired.
static serves two purposes:
inside a block in a function body, it states that: despite the variable has visibility only in the inside of the block where it is defined, its life is all the program life (it is not created/destroyed when the program enters/exist the definition block)
outside a block, it gives local file visibility (the variable name is exposed nowhere out of the definition compilation unit). But that doesn't imply that there's no accessability to that global chunk of memory. You can, if you have a pointer reference pointing to it, still modify it as you want.
#include just text includes the include file contents verbatim in the compilation flow, so everything declared static in the include file has visibility in the including file (after the point of inclussion), and locally in every compilation unit that also includes the header file. But all definitions of it are different and independent, and they don't refer to the same variable (as they are local definitions in different compilation units), as it happens if you name two local variables of different blocks (even when nesting the blocks) with the same name, they are different variables.
If I now want to use this library in my code, I would #include "library.c" at the top of my code.
That will only work if you use this library in a single source file.
As soon as you add foo.c and bar.c which both #include "library.c" and try to link them together, you would get a multiply-defined function1 and function2 symbol error (because each of foo.o and bar.o will now provide their own separate definitions.
You could fix this by making the functions static as well: static void function1() { ... }, etc. but this not how people usually use libraries, because that method causes long compile times and larger than necessary executable. In addition, if you are using this method, you don't need the library.h file at all.
Instead, what people usually do is compile library.c into library.o, #include "library.h" at the top of their source files, then link everything together.
I don't want to expose that array to non library code, so I declare it as static like so:
That is a valid thing to do, and achieves your purpose (so long as you #include "library.h" and not library.c).
Note that using global arrays (as well as most other globals) makes code harder to reason about, and causes additional difficulties when making code thread-safe, and thus it's best to use globals very sparingly.
main file (prog.c):
#include "log.c"
#include "library.c"
static char * Foo;
If some variable (char * Foo) is defined in main file (prog.c), and it is required by log.c function called from library.c, how to correctly declare Foo to be visible from log.c's namespace?
Add its declaration to some .h file that is included in both .c files. Define it in one of the files.
Of course, it can't be declared static for this to work since the static keyword is a promise that the name won't be needed outside of that particular module.
For example, in prog.h:
extern char *Foo;
in prog.c:
#include "prog.h"
#include "log.c"
#include "library.c"
char * Foo; // make sure that Foo has a definition
// some code probably wants to make Foo have a value other than NULL
in log.c:
//... other includes
#include "prog.h" // and now Foo is a known name
// some code here is using the global variable Foo
Now, for the bad news.
Doing this sort of thing creates a coupling between the prog.c and log.c modules. That coupling adds to the maintenance cost of your application as a whole. One reason is that there is no way to prevent other modules from using the global variable also. Worse, they might be using it completely by accident, because its name is insufficiently descriptive.
Worse, globals make it much more difficult to move from single-threaded programs to multi-threaded programs. Every global variable that might be accessed from more than one thread is a potential source of really hard to diagnose bugs. The cure is to guard information that must be global with synchronization objects, but overused that can result in an application where all the threads are blocked except the one that is currently using the global, making the multi-threaded application effectively single threaded.
There certainly are times when the inter-module coupling implied by global variables is acceptable. One use case is for general purpose application-wide options. For instance, if your application supports a --verbose option that makes it chatter while it works, then it makes sense for the flag that is set by the option and tested throughout the code would be a global variable.
There are certainly questions at SO that delve deeply into the pitfalls of globals and will provide guidance on their sensible use.
It is aconventional to include the library source code in your main program:
#include "log.c"
#include "library.c"
static char * Foo;
(The semi-colon is needed.)
However, given that is what you are doing, if "log.c" needs to see the declaration, you could simply do:
static char * Foo;
#include "log.c"
#include "library.c"
Now the static declaration is visible to "log.c" (and "library.c").
If you go for a more conventional setup, then you would have the code in "log.c" access a global variable declared in an appropriate header (rather than a file static variables). However, such dependencies (where a library file depends on a global variable) are a nuisance. The main program (or some piece of code) has to provide the variable definition. It would be better to have the code in "log.c" define the variable, and the (presumed) header "log.h" would declare the variable, and then the main program would set the variable accordingly. Or, better, the code in "log.c" would provide a function or several functions to manipulate the variable, and the header would declare those functions, and the main program would use them.
You want extern. When you extern a variable name you're making a "promise" that the variable will exist when you link. You want to give it storage in a .c file but extern it in a header. That way it's just instantiated once, in the .c's object file. You don't want to have two different .o's using the same name to refer to different locations in memory. (As noted above it's nearly always bad form to require something like this for a library.)
So in a common header you'd have
common.h
extern Foo bar;
Then in prog.c
Foo bar;
And when you included common.h in log.c you could access bar from prog.c
Note that static is very different in C than in Java. In Java it's global to an Class and available for anyone, even without an instance of the class. In C static means that variable is not visible outside of the compilation unit.
The simple answer is:
static char * Foo;
#include "log.c"
#include "library.c"
Which makes Foo visible in log.c and library.c simply by virtue of the "declare before use" rule.
However what you really need to know is that this is nasty code! You have committed at least two sins; Use of global variables and failure to understand the use separate compilation and linking.
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!
Splint gives me the following warning:
encrypt.c:4:8: Function exported but not used outside encrypt: flip
A declaration is exported, but not used outside this module. Declaration can
use static qualifier. (Use -exportlocal to inhibit warning)
encrypt.c:10:1: Definition of flip
Since I called splint only on this file how does it know that?
#include <stdio.h>
#include <stdlib.h>
int flip( int a)
{
int b;
b = a;
b ^= 0x000C;
return b;
}
int blah(int argc, char *argv[]) {
FILE *fp = NULL, *fpOut=NULL;
int ch;
ch = 20; flip(20); return (ERROR_SUCCESS);
}
I even got rid of main so that it could not figure out that the file is complete in any way. I am totally stumped!
You might find that if you included a header that declared flip() - as you should, of course - then splint would not complain. You should also declare blah() in the header as well.
I'm not wholly convinced that this is the explanation because blah() is not used at all (though it uses flip()) and you don't mention splint complaining about that.
However, it is a good practice to make every function (in C) static until you can demonstrate that it is needed outside its source file, and then you ensure that there is a header that declares the function, and that header is used in the file that defines the function and in every file that uses the function.
In C++, the 'every function should be static' advice becomes 'every function should be defined in the anonymous namespace'.
Since I called splint only on this file how does it know that?
You have answered your question. You've fed in one file to lint, so lint knows there is only file to be taken care of (apart from the standard header includes, of course).
int flip() is not declared as static, so it can be potentially used externally. Since you invoked splint with only one source file, it correctly says that your function, if not used externally, must be declared static
It can only report on what it sees. Ignore the warning or follow the instructions to inhibit it if you know better than what it says. Don't assume that a tool like this necessarily knows your program better than you do.
If it really is not intended to be used outside of the file, you can declare it static and it should correct the problem, but it will be inaccessible from other files.