Is it possible to avoid the entry point (main) in a C program. In the below code, is it possible to invoke the func()
call without calling via main()
in the below program ? If Yes, how to do it and when would it be required and why is such a provision given ?
int func(void)
{
printf("This is func \n");
return 0;
}
int main(void)
{
printf("This is main \n");
return 0;
}
Rename main to be func and func to be main and call func from name.
If you have access to the source, you can do this and it's easy.
If you're using gcc, I found a thread that said you can use the
-e
command-line parameter to specify a different entry point; so you could usefunc
as your entry point, which would leavemain
unused.Note that this doesn't actually let you call another routine instead of
main
. Instead, it lets you call another routine instead of_start
, which is the libc startup routine -- it does some setup and then it callsmain
. So if you do this, you'll lose some of the initialization code that's built into your runtime library, which might include things like parsing command-line arguments. Read up on this parameter before using it.If you're using another compiler, there may or may not be a parameter for this.
A rule of thumb would be that the loader supplied by the system would always run main. With sufficient authority and competence you could theoretically write a different loader that did something else.
When building embedded systems firmware to run directly from ROM, I often will avoid naming the entry point
main()
to emphasize to a code reviewer the special nature of the code. In these cases, I am supplying a customized version of the C runtime startup module, so it is easy to replace its call tomain()
with another name such asBootLoader()
.I (or my vendor) almost always have to customize the C runtime startup in these systems because it isn't unusual for the RAM to require initialization code for it to begin operating correctly. For instance, typical DRAM chips require a surprising amount of configuration of their controlling hardware, and often require a substantial (thousands of bus clock cycles) delay before they are useful. Until that is complete, there may not even be a place to put the call stack so the startup code may not be able to call any functions. Even if the RAM devices are operational at power on, there is almost always some amount of chip select hardware or an FPGA or two that requires initialization before it is safe to let the C runtime start its initialization.
When a program written in C loads and starts, some component is responsible for making the environment in which
main()
is called exist. In Unix, linux, Windows, and other interactive environments, much of that effort is a natural consequence of the OS component that loads the program. However, even in these environments there is some amount of initialization work to do beforemain()
can be called. If the code is really C++, then there can be a substantial amount of work that includes calling the constructors for all global object instances.The details of all of this are handled by the linker and its configuration and control files. The linker ld(1) has a very elaborate control file that tells it exactly what segments to include in the output, at what addresses, and in what order. Finding the linker control file you are implicitly using for your toolchain and reading it can be instructive, as can the reference manual for the linker itself and the ABI standard your executables must follow in order to run.
Edit: To more directly answer the question as asked in a more common context: "Can you call foo instead of main?" The answer is "Maybe, but but only by being tricky".
On Windows, an executable and a DLL are very nearly the same format of file. It is possible to write a program that loads an arbitrary DLL named at runtime, and locates an arbitrary function within it, and calls it. One such program actually ships as part of a standard Windows distribution:
rundll32.exe
.Since a .EXE file can be loaded and inspected by the same APIs that handle .DLL files, in principle if the .EXE has an EXPORTS section that names the function
foo
, then a similar utility could be written to load and invoke it. You don't need to do anything special withmain
, of course, since that will be the natural entry point. Of course, the C runtime that was initialized in your utility might not be the same C runtime that was linked with your executable. (Google for "DLL Hell" for hint.) In that case, your utility might need to be smarter. For instance, it could act as a debugger, load the EXE with a break point atmain
, run to that break point, then change the PC to point at or intofoo
and continue from there.Some kind of similar trickery might be possible on Linux since .so files are also similar in some respects to true executables. Certainly, the approach of acting like a debugger could be made to work.
If you are using an open source compiler such as GCC or a compiler targeted at embedded systems you can modify the C runtime startup (CRT) to start at any entry point you need. In GCC this code is in crt0.s. Generally this code is partially or wholly in assembler, for most embedded systems compilers example or default start-up code will be provided.
However a simpler approach is to simply 'hide' main() in a static library that you link to your code. If that implementation of main() looks like:
Then it will look to all intents and purposes as if the user entry point is func(). This is how many application frameworks with entry points other than main() work. Note that because it is in a static library, any user definition of main() will override that static library version.
The solution depends on the compiler and linker which you use. Always is that not
main
is the real entry point of the application. The real entry point makes some initializations and call for examplemain
. If you write programs for Windows using Visual Studio, you can use /ENTRY switch of the linker to overwrite the default entry pointmainCRTStartup
and callfunc()
instead ofmain()
:If is a standard practice if you write the most small application. In the case you will receive restrictions in the usage of C-Runtime functions. You should use Windows API function instead of C-Runtime function. For example instead of
printf("This is func \n")
you should useOutputString(TEXT("This is func \n"))
whereOutputString
are implemented only with respect ofWriteFile
orWriteConsole
: