1

There are some rules for main() function in the Standard.
If the function is called by the OS,
the value of argc is non-negative,
the return value is 0 by default, etc.

On the other hand, main() can be called by other functions,
thus implying recursive execution of main().

In this case, if main() is called by another function,
is it still true that the return value is 0 by default,
or that argc has to be non-negative?

pablo1977
  • 4,281
  • 1
  • 15
  • 41
  • What do you mean by the return value being zero by default? A return value is required if the return type isn't `void`. If it's `int` then a value is required. – markw Jan 01 '21 at 23:20
  • 1
    https://stackoverflow.com/questions/4238179/calling-main-in-main-in-c – bolov Jan 01 '21 at 23:21
  • 1
    @markw `main` can omit the return statement, in which case it implicitly `return 0` – bolov Jan 01 '21 at 23:22
  • 1
    1. `main` doesn't know what's calling it. It's a function: given the same inputs, it will behave the same way unless explicitly made to do otherwise. 2. The standard is specifying how the OS shall invoke `main`. That doesn't constrain how *you* explicitly call `main`. If you want to pass a negative `argc`, that's your choice, but you'd have to ensure that your `main` implementation handles it. – jamesdlin Jan 01 '21 at 23:33
  • @jamesdlin I understand your point. It is what comomon sense dictates to me. However, the standard is tricky. For example, your assertion 1 is not necessarily true. The standard distinguishes among "initial" execution of `main()` (where the return is done as if `exit()` is called) or not. Respect to your point 2, I am able of handle cases like `argc < 0`. My point is that probably the standard is not clear here, when referring to only-startup situations or not. – pablo1977 Jan 01 '21 at 23:49

3 Answers3

1

The rule about the return statement is that if execution reaches the end of main without encountering a return statement, then it behaves as if return 0; were present.

There is no special case for "only the outermost invocation of main" or anything.

It certainly is possible to recursively call main with different values for the arguments -- obviously if you do this in your program then you will need to write the code in main in such a way to handle that in a well-defined manner.

C11 standard quote 5.1.2.2.3/1:

If the return type of the main function is a type compatible with int, a return from the initial call to the main function is equivalent to calling the exit function with the value returned by the main function as its argument; reaching the } that terminates the main function returns a value of 0. If the return type is not compatible with int, the termination status returned to the host environment is unspecified.

M.M
  • 138,810
  • 21
  • 208
  • 365
  • Thank you for your answer. However, what happens with the startup conditions? I can write a sentence like `main( -1, NULL);`, so that `argc < 0`. Is this an invalid call of `main()` function? – pablo1977 Jan 01 '21 at 23:32
  • Incidentally, I once saw `void main(void *fp);` It's not as wrong as it looks because the startup code really did pass a `void *` pointer. Might be some fun getting that code to compile today though. – Joshua Jan 01 '21 at 23:32
  • 1
    @pablo1977: No, it's not. If you pass stuff like that you have to handle it though. – Joshua Jan 01 '21 at 23:33
  • @Joshua there can be implementation-defined definitions of main (in addition to the standard ones, in a hosted implementation) – M.M Jan 01 '21 at 23:36
  • A fairly common bug is for programs to output `argv[0]` without checking argc at all , incorrectly assuming that argv[0] always holds the program name – M.M Jan 01 '21 at 23:38
  • This answer seems to be wrong. The standard clearly states the special rule for return from `main` holds only for the *initial call to the function `main`*. – Jens Gustedt Jan 02 '21 at 10:16
  • @JensGustedt I added quote to my answer for easy reference. The "initial call" text is a part of the sentence talking about a return from the initial call being equivalent to `exit`. The part about reaching the `}` comes after a semicolon; I would think that (in general) conditional clauses before a semicolon don't reach to text after the semicolon – M.M Jan 02 '21 at 10:36
  • @M.M, no, I don't think so. With your interpretation a semicolon in the text would be useless and a period to split this up in two phrases would do just the same. In fact, the semicolon is used in the standard to add details to the previous part. You can see that more clearly in the text on the program name, some paras above. – Jens Gustedt Jan 02 '21 at 13:43
1

As already others have stated, there is no restriction about argc. These requirements are expressed in the clause 5.1.2.2.1 (Program startup) and so they only concern the arguments with which main is called initially.

Similarily, the relaxation of the rules for the return of main are found in clause 5.1.2.2.3 (Program termination). To make that even clearer the text states that this only concerns the initial call to main. The text is

If the return type of the `main` function is a type
compatible with `int`, a return from the initial call
to the `main` function is equivalent to calling the `exit`
function with the value returned by the main
function as its argument; reaching the `}` that terminates 
the `main` function returns a value of `0`.

The ";" within the phrase clearly implies that the conditions of the start of the phrase are still valid for the last sub-phrase.

All of this is only valid within 5.1.2.2 (Hosted environment), so freestanding environments may invent their own rules, but which then are not covered by the C standard.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • Hi, Jens. Thank you for your answer. After reading carefully the standard, I agreed with your ";" conclusion. The paragrah 5.1.2.2.1 can be interpreted as you say if one assumes that the title *Program startup* is what one takes as the meaning for the whole paragraph. However, I still consider that the wording in the standard is not clear. On the other hand, I think that common sense dictates your conclusion, since the `main()` function seems to accept any valid set of values as arguments in not initial calls (such a believe is shared by other developers, as some comments have shown here). – pablo1977 Jan 02 '21 at 13:09
  • I accept your answer, but I have doubts with the matter anyway. Thx. – pablo1977 Jan 02 '21 at 15:08
0

The main() function is not called by the OS. The OS loads the executable in memory and gives control to a piece of code that:

  • prepares the arguments of main() and calls it;
  • gets the value returned by main() and passes it back to the OS using a mechanism that is specific to the OS; it uses 0 as a default value when main() does not return anything;
  • does other things that are not relevant to the discussion.

This piece of code belongs to your program and is provided by the standard C library.

main() is just a regular function, there is nothing special about it except its name. The Windows executables, for example, use the function WinMain() instead of main() for the same purpose.

You can call main() the same way you call any other function of your program and it behaves the same way as any other function of the program.

axiac
  • 68,258
  • 9
  • 99
  • 134