15

My only exposure to programming has been Java,where I have not encountered (up to now) different conventions for writing the main method.I have been following to sources for learning c (K&R AND C Programming A Modern Approach) where they use very different forms of the main method (function).

K&R version up to now:

main() {
    blah blah blah;
}

C Programming A Modern Approach

int main() {
    blah blah blah;
    return 0;
}

OR

int main() {
    blah blah blah; 
    //returns nothing
}

To make matters more confusing I have seen people do :

int main(void) {
    blah blah blah;
}

while they either returned 0 or did not. I don't in my very uneducated assumption think this is only a standards issue but maybe something a bit more conceptual or deep. Could someone shed some light on this issue?

dbush
  • 205,898
  • 23
  • 218
  • 273
AliMan
  • 155
  • 7
  • 1
    @SuvarnaPattayil not sure about that. It's **very close** and might very well be a duplicate, but at least this question specifically asks about styles found in some sources, including K&R ... –  Aug 14 '17 at 18:05
  • 2
    @FelixPalmen It's a canonical dupe - any possible answer to this question is already there or linked to there. – J... Aug 14 '17 at 19:10
  • **C** Language does not have Methods. – Michi Aug 14 '17 at 19:13
  • Another variant you will often see is returning the constant `EXIT_SUCCESS` or `EXIT_FAILURE` from ``, rather than the magic number `0`. – Davislor Aug 14 '17 at 19:48
  • Some of the answers mention that the standard gives compilers permission to add “implementation-defined” alternative forms for `main()`. Many compilers allow the return type of `main()` to be `void`, some I’ve used allow it to take a third argument (a list of environment variables), and some allow it to be called with only one argument. None of these options strictly conform to the standard. – Davislor Aug 14 '17 at 19:57

4 Answers4

14
  • K&R style is outdated and isn't correct according to the C standard any more.

  • Valid signatures are

    int main(void)
    

    and

    int main(int argc, char *argv[])
    

    or, equivalent because an array type in a function is adjusted to a pointer type anyways:

    int main(int argc, char **argv)
    
  • The signature

    int main()
    

    happens to be valid as well, because an empty argument list means any number of arguments, that aren't described *). AFAIK, this is subject to change, so don't write it this way. Writing void is how you express this function doesn't take arguments in C.

  • Implementations of C are free to provide other implementation-defined entry points. But the two I listed above are the only ones guaranteed by the standard.

  • C99 introduced a special rule for main() that states if the function doesn't return anything, a value of 0 is returned implicitly. So only in main, you can skip the return. My advice is: don't. It's just confusing. But this is an opinion.


*) note this is different in C++, where nothing between the parantheses indeed means: no arguments.

  • 4
    *C99 introduced a special rule for `main()` that states if the function doesn't return anything, a value of 0 is returned implicitly. So **only in main**, you can skip the `return`. My advice is: don't. It's just confusing. But this is an opinion.* But it's not just an opinion as there are still [compilers that don't fully implement C99.](https://social.msdn.microsoft.com/Forums/vstudio/en-US/fa17bcdd-7165-4645-a676-ef3797b95918/details-on-c99-support-in-msvc?forum=vcgeneral) – Andrew Henle Aug 14 '17 at 17:49
  • 3
    @Andrew Henle Microsoft is not a very good example as microsoft does not care about C anymore. – 0___________ Aug 14 '17 at 17:54
  • 1
    Also `int main(int argc, char *argv[], char *env[])` where the third is a `NULL` terminated array of environment variable strings - IDK if this is standard. – Weather Vane Aug 14 '17 at 17:58
  • 1
    @WeatherVane that's POSIX (edit: not even specified, but typical in POSIX systems) and by means of the standard falls in the "implementation defined" category, very much like windows' `WinMain()` and friends. –  Aug 14 '17 at 17:59
  • 1
    @PeterJ *Microsoft is not a very good example as microsoft does not care about C anymore.* In my opinion that makes Microsoft a very, very good (bad?) example. If Microsoft is going to claim to have a C compiler, they should at least *try* to meet an almost-twenty-year-old standard. – Andrew Henle Aug 14 '17 at 18:28
  • @Andrew Henle they re going to remove C support soon I think. They only do the minimum necessary needed by the C++ standard. Even setting to compile as C file is hidden deep in the VS17 configurations options. The option to create the C project was removed. And they claim that they have C++ compiler which allows compilation of the C projects – 0___________ Aug 14 '17 at 18:35
5

Pre-standardized versions of C (known as K&R C) had the concept of a default type of int if none was given. So in K&R this:

main() {

Is the same as:

int main() {

As for the difference between int main() and int main(void), an empty parameter list means the function takes an unspecified number of parameters while (void) as a parameter list means the function takes no parameters. The former is acceptable, but the latter is preferred as it is more explicit.

Regarding the use of the return statement, a function with a non-void return type must use return to return a value, except (starting with the C99 standard) for the main function. In the case of main, a missing return statement implies a return value of 0.

Because the implicit return 0 for main was added in C99, you'll see some code that explicitly returns and some that doesn't depending on which version of the standard the programmer is conforming to.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • How can you NOT specify how many arguments a function takes ? By using int main(empty) you are saying it can take arguments,but how can this be the case if the function does not know the type or the amount of arguments it is supposed to take ? – AliMan Aug 14 '17 at 17:52
  • @AliMan by writing nothing between the parantheses in the declaration. –  Aug 14 '17 at 17:52
4

There are two standard signatures for main as of the latest C language standard:

int main( void ) // void indicates "takes no arguments"

and

int main( int argc, char *argv[] ) // or char **argv, it means the same thing in this context

The names argc and argv are arbitrary; you can use different names if you wish.

Implementations may provide additional valid signatures for main - check your compiler documentation.

If your program does not take any command line arguments, use the first form, otherwise use the second.

C function declaration and definition syntax has evolved a bit over time, which is why different references use different conventions.

Implicit Typing

First of all, C originally allowed for implicit int declarations - if the compiler saw a function definition or declaration without a type specifier, it assumed the function returned int:

foo(); // modern equivalent: int foo( void )

This was allowed up until the 1999 standard, although was considered bad style by most of us long before then.

The void keyword was not introduced until the 1989 standard. As a type specifier, it indicates a type with no values. As an identifier in a function parameter list, it indicates that the function takes no arguments.

Before the introduction of the void keyword, there was no good way (other than documentation) to distinguish between functions that returned a value you were meant to use vs. functions that just executed some action. Some of us used the "implicit int" convention to indicate those functions weren't meant to return anything meaningful:

foo();     /* returns int, but return value not meant to be used */
int bar(); /* returns int, return value meant to be used */

Again, this was just a convention, and far from universal. Now we'd use the void keyword:

void foo(); /* does not return a value */
int bar();  /* returns int */

Function Prototype Syntax

Originally, a function definition looked something like this:

foo( bar, bletch, blurga )
  int bar;
  double bletch;
  char *blurga;
{
  /* function body */
}

The parameter list only specified the names of the parameters, not their types; that was done in a separate set of declarations between the function declarator and the opening { of the function body. A function that took no arguments had an empty identifier list in the function definition:

blah( )  
{
  /* function body */
}

Function declarations only specified the name and return type of the function; it didn't specify the parameters at all:

foo( ); /* no bar, bletch, or blurga */

An empty identifier list in a function declaration indicates that the function takes an unspecified number of arguments, not zero arguments. The compiler could check that the return type of the function call was being used correctly, but it could not check that the number and types of parameters in the call were correct.

The 1989 language standard introduced the concept of function prototype syntax, where the type of each parameter was specified along with its name in the parameter list:

foo( int bar, double bletch, char *blurga )
{
  /* function body */
}

This applied to both the function declaration and definition:

foo( int bar, double bletch, char *blurga );

This change allowed the compiler to check that the number and types of parameters in a function call were correct, along with the return type. In addition, the void keyword could be used in the parameter list to indicate that the function took no parameters, in both the definition and declaration:

blah( void ); /* declaration, returns int, takes no parameters */

blah( void )  /* definition */
{
   /* function body */
}

So yeah, depending on which language revision you're working against, main would be written differently:

K&R:

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

C89:

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

C99 and later:

int main( void )                  int main( int argc, char *argv[] )
{                                 {
  ...                               ...
}                                 }
John Bode
  • 119,563
  • 19
  • 122
  • 198
  • Thanks.I cannot up vote your answer due to restrictions on my account.But you truly illuminated my understanding. – AliMan Aug 14 '17 at 19:57
  • Excellent answer. You know this, of course, but to add a bit of context: the old-fashioned, any-number-of-unchecked-arguments kind of function was replaced by the *varargs* style function. People learning C will first encounter this as `int printf( const char* format, ... );` which has any number of arguments of any type *after the first one*. Compilers are now smart enough to type-check the arguments of `printf()`. This was the original use case for being able to call functions with a different number and type of arguments. It’s now done another, source-compatible way. – Davislor Aug 14 '17 at 20:06
3

C standard defines signature for main either as

int main(void)

or

int main(int argc, char *argv[])

Adding return 0; as a last statement in main function is optional.
Standard also says about some implementation defined prototype. int main() is accepted by GCC compiler.

main() is an old school prototype and almost deprecated.

haccks
  • 104,019
  • 25
  • 176
  • 264