44

Well the title says it all. Is a main() function absolutely essential for a C program?

I am asking this because I was looking at the Linux kernel code, and I didn't see a main() function.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
elricL
  • 1,188
  • 3
  • 11
  • 20
  • possible duplicate of [Avoiding the main (entry point) in a C program](http://stackoverflow.com/questions/3379190/avoiding-the-main-entry-point-in-a-c-program) – Jens Gustedt Nov 06 '10 at 15:39
  • 10
    You're really stretching it there, Jens, in calling this a duplicate. – JUST MY correct OPINION Nov 06 '10 at 15:43
  • 2
    I don't see that as a dupe myself. That was one of those annoying interview questions, this seems a more serious inquiry as to how Linux starts up. – paxdiablo Nov 06 '10 at 15:44
  • Well,I was just looking at the Linux source,and the question popped.I did search before posting and I didn't think how to avoid main() and the necessity of main,were the same question.Honest mistake. – elricL Nov 06 '10 at 16:00
  • 2
    It wasn't a mistake at all, @Mad-scientist. Jens is jumping the gun big time. – JUST MY correct OPINION Nov 07 '10 at 03:21

7 Answers7

64

No, the ISO C standard states that a main function is only required for a hosted environment (such as one with an underlying OS).

For a freestanding environment like an embedded system (or an operating system itself), it's implementation defined. From C99 5.1.2:

Two execution environments are defined: freestanding and hosted. In both cases, program startup occurs when a designated C function is called by the execution environment.

In a freestanding environment (in which C program execution may take place without any benefit of an operating system), the name and type of the function called at program startup are implementation-defined.

As to how Linux itself starts, the start point for the Linux kernel is start_kernel though, for a more complete picture of the entire boot process, you should start here.

Community
  • 1
  • 1
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 17
    Wherever the implementor wants it to be. – R.. GitHub STOP HELPING ICE Nov 06 '10 at 15:42
  • @Mad-scientist, see the update re `start_kernel` in `init/main.c`. – paxdiablo Nov 06 '10 at 15:42
  • Actually,I get the understand the answer after reading it again.If its some kinda embedded system,there wont be any fixed starting point,it can be started by switches,or resets. Thank you. – elricL Nov 06 '10 at 15:45
  • Even if the C standard said nothing about free-standing implementations and insisted that every program must have a main, the Linux kernel still wouldn't require one because, hey gee golly, it isn't a conforming program. Which means that you have no assurance that you can compile it on your Windows box with MSVC and have it perform correctly -- but then you didn't expect to be able to, did you? Most people here don't understand the Standard -- it makes certain assurances if you do certain things, but it can't prevent things from working if you don't. – Jim Balter Feb 21 '11 at 12:02
  • @Mad-scientist No, you didn't understand it. main isn't a "fixed starting point", it's an arbitrary location in the program which is recorded in the executable by the linker. But other names can be chosen, and another one is for Linux. And the C standard is irrelevant here because the Linux kernel is not a conforming program and it is not compiled by a conforming implementation -- certainly not with the flags that are used to build the Linux kernel. Some silly people say "but then it could set off a thermonuclear bomb" -- they don't understand how the Standard works. – Jim Balter Feb 21 '11 at 12:34
  • @agf, hmm, the Chinese site seems to have gone walkabout. Replaced them with some TLDP pages. – paxdiablo Oct 14 '11 at 07:59
11

Well, no, but ...

C99 specifies that main() is called in the hosted environment "at program startup", however, you don't have to use the C runtime support. Your operating system executes image files and starts a program at an address provided by the linker.

If you are willing to write your program to conform to the operating system's requirements rather than C99's, you can do it without main(). The more modern (and complex) the system, though, the more trouble you will have with the C library making assumptions that the standard runtime startup is used.

Here is an example for Linux...

$ cat > nomain.S
.text
_start:
    call    iamnotmain
    movl    $0xfc, %eax
    xorl    %ebx, %ebx
    int     $0x80
.globl _start
$ cat > demo.c

void iamnotmain(void) {
    static char s[] = "hello, world\n";
    write(1, s, sizeof s);
}
$ as -o nomain.o nomain.S
$ cc -c demo.c
$ ld -static nomain.o demo.o -lc
$ ./a.out
hello, world

It's arguably not "a C99 program" now, though, just a "Linux program" with a object module written in C.

DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
  • +1. I would _still_ consider that a C99 program, just a freestanding one. Nothing in the standard states that you _have_ to use the OS just because it's there :-) – paxdiablo Nov 08 '10 at 00:51
9

The main() function is called by an object file included with the libc. Since the kernel doesn't link against the libc it has its own entry point, written in assembler.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
3

Paxdiablo's answer covers two of the cases where you won't encounter a main. Let me add a couple of more:

  • Many plug-in systems for other programs (like, say, browsers or text editors or the like) have no main().
  • Windows programs written in C have no main(). (They have a WinMain() instead.)
Community
  • 1
  • 1
JUST MY correct OPINION
  • 35,674
  • 17
  • 77
  • 99
  • 7
    Windows programs have WinMain, because the main() function would be in the stub, which does some stuff and then calls WinMain. – Kinjal Dixit Nov 06 '10 at 19:23
  • Just like GCC programs, say, have a `main()` because `_start()` (I think) is in the boilerplate code in `libc` which does some stuff and then calls `main()`. I'm not sure what your point is here. Or did you think that `main()` is called directly by the operating system? – JUST MY correct OPINION Nov 07 '10 at 03:15
0

The operating systems loader has to call a single entry point; in the GNU compiler, the entry point is defined in the crt0.o linked object file, the source for this is the assembler file crt0.s - that invokes main() after performing various run-time start-up tasks (such as establishing a stack, static initialisation). So when building an executable that links the default crt0.o, you must have a main(), otherwise you will get a linker error since in crt0.o main() is an unresolved symbol.

It would be possible (if somewhat perverse and unnecessary) to modify crt0.s to call a different entry point. Just make sure that you make such an object file specific to your project rather than modifying the default version, or you will break every build on that machine.

The OS itself has its own C runtime start-up (which will be called from the bootloader) so can call any entry point it wishes. I have not looked at the Linux source, but imagine that it has its own crt0.s that will call whatever the C code entry point is.

Clifford
  • 88,407
  • 13
  • 85
  • 165
0

main is called by glibc,that is a part of application(ring 3), not the kernel(ring 0).
the driver has another entry point,for example windows driver base on WDM is start from DRIVERENTRY

Sim Sun
  • 587
  • 1
  • 4
  • 28
-2

In machine language things get executed sequentially, what comes first is executed first. So, the default is for the compiler place a call to you main method to fit the C standard.

Your program works like a library, which is a collection of compiled functions. The main difference between a library and a standard executable is that for the second one the compiler generates assembly code which calls one of the functions in your program.

But you could write assembly code which calls your an arbitrary C program function (the same way calls to library functions work, actually) and this would work the same way other executables do. But the thing is you cannot do it in plain standard C, you have to resort to assembly or even some other compiler specific tricks.

This was intended as a general and superficial explanation, there are some technical differences I avoided on purpose as they don't seem relevant.

agf
  • 171,228
  • 44
  • 289
  • 238
Trinidad
  • 2,756
  • 2
  • 25
  • 43