22

I know that in C compilers the main() function is called by the _start() function which has code something like this:

exit(main()); // return value of main is returned

How does _start() work when main() does not return int, for example if its return type is void, float, or something else?

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
Utkarsh Srivastav
  • 3,105
  • 7
  • 34
  • 53
  • I would image function pointer casting, but I'd like to hear from someone who knows the truth. Can't wait for the answer. :D – shinkou Jan 13 '12 at 01:50
  • 5
    The restrictions on the return value of main are different in C and C++ – fefe Jan 13 '12 at 01:51
  • @fefe - Really? I thought both were required to return int - got the standard para numbers so I can read? I have C99 and C++89, C++11 – Adrian Cornish Jan 13 '12 at 02:00
  • @Adrian for C it's 5.1.2.2.1. – Daniel Fischer Jan 13 '12 at 02:17
  • @DanielFischer right, but how is that different from the C++ version. Found it C+11 says "It shall have a return type of type int," on 3.6.1.2 – Adrian Cornish Jan 13 '12 at 02:20
  • I'm told that the C runtime in Linux, i.e. `crt1.o`, which contains your `_start()`, is written in assembler directly, so it doesn't *have* a type system. Whatever ends up in the expected memory location (or register) will be used as your return value... – Kerrek SB Jan 13 '12 at 02:38
  • @KerrekSB does it matter - if you just say c/c++ then it must work on every single implantation of the language no matter if its linux box or a washing machine. – Adrian Cornish Jan 13 '12 at 02:43
  • 1
    Ok C99 5.1.22.1.1 says "It shall be defined with a return type of int" c++14882 3.6.1.1 says "It shall have a return type of type int" and c++14882-2011 3.6.1.1 says "It shall have a return type of type int" so @fefe they seem clearly defined to be the same between C and C++ – Adrian Cornish Jan 13 '12 at 02:54
  • @AdrianCornish: I thought we already agreed that it wasn't a standard-conforming program if `main()` didn't return `int` ... I just wanted to indicate what might happen. Of course "ill-formed" program is the only canonical answer. – Kerrek SB Jan 13 '12 at 02:56
  • @KerrekSB Apologies - I missed any agreement about non conforming code. – Adrian Cornish Jan 13 '12 at 02:59
  • The C standard allows for implementations to explicitly define other return types for `main`. Of course, then your program isn't portable. But it's not *necessarily* undefined behaviour. – detly Jan 13 '12 at 08:46
  • Possibly related: [Why main does not return 0 here?](http://stackoverflow.com/questions/8677672/why-main-does-not-return-0-here) – user Jan 13 '12 at 09:33

8 Answers8

15

If main doesn't return int, then you have an ill-formed program and behavior is undefined. Anything can happen. Your program might crash, or it might run as though nothing were wrong at all.

Let's suppose main returned something other than int, and your compiler and linker allowed the program to be made. The caller doesn't know that, though. If the caller expects returned int values to be returned in the EAX (Intel) register, then that's what it will read to determine the return value of main. If your faulty main stored a float value there, then it will be interpreted as an int instead. (That doesn't mean it will get truncated. It means the bits making up the layout of a floating-point value will instead make up an int instead.) If your faulty main returned void, then it didn't store anything in the expected register, so the caller will get whatever value was previously stored in that register instead.

If your main returns some type that it expects to store someplace that the caller didn't' reserve memory for (such as a large struct), then it will end up overwriting something else, perhaps something important to the clean shutdown of the program, causing your program to crash.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • 3
    How can you store a float in EAX? – Kerrek SB Jan 13 '12 at 03:18
  • 1
    @KerrekSB - Good question. Though, pre-80486 it was relatively common. After all, a float is just 32 bits of stuff that you use special rules to operate on. – Omnifarious Jan 13 '12 at 04:03
  • 1
    Are floats returned in registers, @Kerrek? I don't know. In the imaginary scenario I described in my answer, `main` has indeed — somehow — stored a float in the place where the caller expected an int to go. Behavior is undefined, so I can describe any strange workings I want! – Rob Kennedy Jan 13 '12 at 04:12
  • 1
    @RobKennedy: Floats are usually returned in the floating point registers of your FPU (like the 80387, or maybe this modern MMX thing). – Kerrek SB Jan 13 '12 at 04:29
  • x86 `cdecl` returns a float in `ST0`. The new SIMD registers are only used in x64, where `XMM0` contains the FP return value. – MSalters Jan 13 '12 at 08:19
  • In C, `main` may return something other than `int` if the implementation permits it -- but there's rarely any good reason to do so in a hosted implementation. – Keith Thompson Dec 18 '12 at 18:56
15

The C standard never mentions this _start function; I don't believe C++ does either.

In C prior to the 1999 ISO standard, if execution reaches the end of main() without executing a return statement, or executes a return statement that doesn't specify a value, then "the termination status returned to the host environment is undefined". In practice, I've seen implementations where such a program returns a status of 1 (failure), or some arbitrary value in memory such as the result of the last function that was called.

The 1999 ISO C standard changed this: "reaching the } that terminates the main function returns a value of 0". This matches the rule that C++ has had at least since the first ISO C++ standard in 1998.

(As a matter of style, I prefer to have an explicit return 0; at the end of main, even if it's not strictly required. This is consistent with int functions other than main, and it makes for better portability to pre-C99 C compilers.)

All this assumes that main is defined with a return type of int. That's the only type that's specifically supported by the C standard (either int main(void) or int main(int argc, char *argv[]) or equivalent), but (hosted) implementations may support other implementation-defined definitions. The C90 standard doesn't explicitly cover this case, but C99 says, "If the return type is not compatible with int, the termination status returned to the host environment is unspecified."

The C++ standard is a bit different. For hosted implementations, main must be defined to return int. The parameters are implementation-defined, but both the standard forms of C must be supported.

For a hosted implementation in either C or C++, there is no good reason I know of to define main with a return type other than int. Just use one of the two standard definitions, and the question won't arise.

For "freestanding implementations", "the name and type of the function called at program startup are implementation-defined". So the entry point might legitimately return void or something else, and it might not even be called main. Note that a "freestanding implementation" is one "in which C program execution may take place without any benefit of an operating system", typically an embedded system.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • Would not system kernel development also count as a "freestanding implementation" under that definition? Of course, if an OS kernel reaches the end of the entry point function, you've got a problem... – user Jan 13 '12 at 09:37
  • @MichaelKjörling: Probably. In practice an implementation is "freestanding" if the implementer says it is (and conforms to the weaker requirements for freestanding implementations). – Keith Thompson Jan 13 '12 at 10:03
  • @KeithThompson: prior to C99 if execution reaches the end of main() without executing a return statement, or executes a return statement that doesn't specify a value, then "the termination status returned to the host environment is unspecfied" not undefined. – Destructor Jan 19 '16 at 07:42
  • @PravasiMeet: What is your source for that quotation? The C90 standard, section 5.1.2.2.3, says: "If the main function executes a return that specifies no value, the termination status returned to the host environment is **undefined**." (emphasis added) Certainly "unspecified" would have made more sense. – Keith Thompson Jan 19 '16 at 16:54
8

The function will return an implementation-defined value. For example, in C++, main implicitly returns 0. In this case of a void main then this would simply be returned by _start. However, there are virtually no implementations that would allow any arbitrary return type- it's baked into the operating system that a process exits with an integral value.

Puppy
  • 144,682
  • 38
  • 256
  • 465
7

In C++ it would be a compile error to return anything other than int from main():

error: ‘::main’ must return ‘int’

In C it is a warning, you will get a float reinterpreted as an int: for example, 2.1F would be reinterpreted as 224.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
2

Standard implementations of C expect main to return int just because it is defined that way in the C standard. Returning something other than int (or a type compatible with int) usually results in undefined behaviour—meaning there is no way to tell what will happen.

However, there are non-standard implementations of C, for example, the Plan 9 operating system uses void main(), here is a list their utilities' source code. Plan 9 C code is quite a bit different to K&R, ANSI, C99 or C11. Here's a link explaining how Plan 9 uses the C language.

dreamlax
  • 93,976
  • 29
  • 161
  • 209
2

If the return type of main is not an int then the return value is implementation defined.
In short an Implementation is allowed to have different return type than int for main but none of the known implementations support anything other than int.
Ideally, You will need to refer to the documentation of your platform and the compiler to see what exact behavior it defines because it is allowed to have the flexibility do so by the standard.

Reference:

C++03 Standard:

3.6.1 Main function [basic.start.main]

An implementation shall not predefine the main function. This function shall not be overloaded. It shall have a return type of type int, but otherwise its type is implementation-defined. All implementations shall allow both of the following definitions of main:

int main() { /* ... */ }

and

int main(int argc, char* argv[]) { /* ... */ }

.....

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • Doesn't that mean that it must have a `int` return type, but other than that it can take any arguments, as long as the implementation allows no arguments and `argc`/`argv` (i.e. the *return type* is `int`, but the type of the `main` function is implementation-defined). I'm waiting for coffee to settle in so maybe I'm not making any sense... – dreamlax Jan 13 '12 at 03:32
0

Assume we're using Visual Studio 2012.

For C++ programs, Visual Studio allows void to be specified as the return type, even though this is forbidden by the C++ standard. Under the standard, main() must return an int in hosted implementations.

For C programs, any return type is allowed for main(), but returning something other than an int results in unspecified behavior. For example, under Visual Studio 2012, returning 0.0 from double main() results in a return value of 0xcccccccc when the program is run in the debugger (see In Visual Studio C++, what are the memory allocation representations?).

Community
  • 1
  • 1
bwDraco
  • 2,514
  • 2
  • 33
  • 38
0

The C-standard does not allow you to return any other value than int or void -- the c-compiler specifically test for the signature of main to make sure it is compatible.

Soren
  • 14,402
  • 4
  • 41
  • 67
  • 3
    C99 (and what I saw of the C11 drafts) doesn't mention `void`. Only a return type of `int` is explicitly mentioned 'It shall be defined with a return type of `int`', but unfortunately the sentence ends 'or in some other implementation-defined manner' (5.1.2.2.1) – Daniel Fischer Jan 13 '12 at 02:15
  • Downvoted because of comment of void return 5.1.2.2.1 mentions nothing about void returns – Adrian Cornish Jan 13 '12 at 02:17
  • @DanielFischer: I believe that the "in some other implementation-defined manner" is referring to the parameters and their types, not the return type. – dreamlax Jan 13 '12 at 07:05
  • @dreamlax I believe that's the intention. But as far as my knowledge of English goes, it _can_ be read as if it's allowing arbitrary implementation-defined types. And I've seen it argued thus. Unfortunately it has not been made completely unambiguous that `int` is the _only_ allowed return type (for hosted implementations). – Daniel Fischer Jan 13 '12 at 09:24