Difference between int main() and int main(void)?
Asked Answered
M

10

64

What does the following mean :

int main(void) {...} 

VS

int main() {...}

?

I think that int main() {...} means that main doesn't receive any parameters (from command line) , however:

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

does.

But, what does int main(void) {...} mean? And, what does void stand for ?

I've looked here but it's somehow a different question .

Mcandrew answered 1/9, 2012 at 5:30 Comment(2)
C99 and C11 don't mention int main() anymore. Just use int main(void). See 5.1.2.2.1 "Program startup" of the standard: open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdfLema
Related: Is int main() { } (without “void”) valid and portable in ISO C?Savoirfaire
L
55

In C++, there is no difference.


In C, the difference is questionable. Some love to argue that the latter version (the one without void) is technically just a common implementation extension and not guaranteed to work by the standard because of the wording in the standard. However, the standard clearly states that in a function definition an empty set of parameters has a well-defined behaviour: that the function does not take any parameters. Thus such a definition for main matches the following description in the standard:

It [main] shall be defined with a return type of int and with no parameters.

There is, however, a noticeable difference between the two: namely, the version without void fails to provide a correct prototype for the function:

// this is OK.
int main()
{
  if (0) main(42);
}

// this requires a diagnostic to be shown during compiling
int main(void)
{
  if (0) main(42);
}

Oh, and just to be complete: the void has the following meaning in all function declarators:

(6.7.6.3p10) The special case of an unnamed parameter of type void as the only item in the list specifies that the function has no parameters.

Logging answered 1/9, 2012 at 5:38 Comment(7)
In your 1st example , what does main(42); mean (where you wrote // this is okay)?Mcandrew
It's a function call (of main with a single int argument of 42).Logging
Yes ,but what does it do ? this is the first time that I see an invoke of main() from within main() .Mcandrew
+1 for clearing that myth. I just don't agree with the part that it ain't a prototype. The term "prototype" is not defined through syntax but through semantic, in is a declaration of the function that also declares the types of its arguments. int main() { ... } fits perfectly in, there. Not all compilers agree on that, but that is a different point :)Roustabout
@JensGustedt There's no question about it, but the conclusion is not what you expected. int main() does not provide a prototype. This has been a common discussion point, but the committee has provided an explicit answer in DR #317: "The grammar states that an empty parens stands for an empty identifier list not an empty parameter-type-list."Postobit
Regarding the nonsense about diagnostic for missing prototype, see the standard: "The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters: int main(void)". Furthermore int main() is relying on an obsolescent feature and should therefore not be used, see 6.11.6.Subedit
How is if (0) main(42) able to call main() function? Isnt the if-condition always false? Or is there something happening at compile time?Kell
S
6

First of all, there is a difference of what is allowed for hosted systems and freestanding systems, as shown here.

For hosted systems, 5.1.2.2.1 Program startup applies:

The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters:

int main(void)

... (more text follows regarding argv/argc etc styles).

The interesting part is "with no parameters". int main() and int main (void) are currently equivalent, since they are both function declarators and have no parameters. The following applies (6.7.6.3 ):

10 The special case of an unnamed parameter of type void as the only item in the list specifies that the function has no parameters.

/--/

14 An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters. The empty list in a function declarator that is not part of a definition of that function specifies that no information about the number or types of the parameters is supplied.145)

Emphasis mine, the bold text is what applies to int main(). There is also note 145) at the end of the text, which says "See ‘‘future language directions’’ (6.11.6)":

6.11.6 Function declarators

The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.

And here is the difference. Being a function declarator, int main() is bad style because of the above, since it is not guaranteed to work in the next version of the C standard. It is flagged as an obsolescent feature in C11.

You should therefore always use int main (void) on a hosted system and never int main(), even if the two forms are, for now, equivalent.


In C++ both forms are completely equivalent, but there int main() is the preferred style for subjective, cosmetic reasons (Bjarne Stroustrup says so... which is probably quite a bad rationale for explaining why you do something in a particular way).

Subedit answered 10/7, 2015 at 8:48 Comment(1)
int main() is the preferred style for subjective, cosmetic reasons” – perhaps subjective, ok, but IMO it's still just right. () is clearly an empty tuple. (void) looks like it's a single argument of type void, and then you'd expect to be able to write stuff like main(f()), if f is a function that “returns void”. It's a good idea to make a distinction between empty sets (/lists/arrays/tuples), and one-element sets whose member happens to be vacuous itself. (Apart from that, if objectively it just doesn't matter if you write void or not, then follow Occam's boilerplate razor...Morbific
M
5

In C, in a prototype (not in C++ though) an empty argument list means that the function could take any arguments (in the definition of a function, it means no arguments). In C++, an empty parameter list means no arguments. In C, to get no arguments, you have to use void. See this question for a better explanation.

Mosra answered 1/9, 2012 at 5:37 Comment(6)
That only applies when the declarator is not part of the function definition.Logging
@eq-: Sorry, but that means that it only applies when it is separate from the implementation? So it applies for int foo(void); int foo(void) {} but not for int foo(void) {}?Mosra
In C, int foo(); does not specify anything about the function's parameters, while int foo() {} specifies that foo does not take any parameters.Logging
wrong for C. the standard even has int main() { ... } in its examples.Roustabout
In a definition, empty parens as a definition tell the compiler it takes no arguments, but as a declaration (a non-prototype one at that) indicates that it takes an unspecified number of arguments), so it's kind of both at the same time.Webfoot
In C, prototypes cannot have empty argument lists. If you see a function declaration with an empty argument list, it is not a prototype. (C11 6.2.1/2)Nursemaid
O
4

In C++ having a function foo(void) and foo() is the same thing. However, in C it's different: foo(void) is a function that has no arguments, while foo() is a function with unspecified arguments.

Oklahoma answered 1/9, 2012 at 5:38 Comment(2)
You missed the point (for C). In a definition int foo() { } declares a function without arguments.Roustabout
@JensGustedt in C, in a definition, int foo() { } actually defines a function without arguments, yet it declares a function that takes an unspecified number of arguments.Webfoot
L
3

In C++, there is no difference, both are same.

Both definitions work in C also, but the second definition with void is considered technically better as it clearly specifies that main can only be called without any parameter. In C, if a function signature doesn’t specify any argument, it means that the function can be called with any number of parameters or without any parameters. For example, try to compile and run following two C programs (remember to save your files as .c).

Ligan answered 23/5, 2015 at 3:5 Comment(0)
P
1

In C++, there is no difference between the two, and int main() is a legal signature and return type for main.

Photocurrent answered 1/9, 2012 at 5:31 Comment(0)
M
0

I know the thread is old but this question was bothering me for a while a few years ago so I wanted to throw in my half a cent(if that).

I always treat C functions as if they have fixed amount of arguments regardless of context, unless they use va_args. That is, I trust main to ALWAYS have the prototype:

int main(int argc, char **argv).

even if no arguments are passed, the function has these arguments on the stack because the main function does not have function overloading.

C does have the ability to have primitive overloading through just pretending the argument is not there. In which case, the argument is still passed and is on the stack but you never access it, so it merely reduces size of the source code.

Saying int main() simply means that I know that the function may have parameters, but I am not using them, so I write int main().

Saying int main(void) says that main CERTAINLY has no arguments, and implies that there are two different function prototypes:

int main(void);
int main(int argc, char **argv);

Since C has no function overloading, this is somewhat misleading to me, and I distrust code that has main(void) in it. I would not if main NEVER took any parameters, in which case main(void) would be completely OK.

NOTE: In some implementations, there are more parameters in main than argc and argv, such as env, but this does not bother me because I know that I do not explicitly say that those are the only two parameters, but those are the minimal parameters and it's okay to have more, but not less. This is in contrast to downright saying int main(void) which yells at me as THIS FUNCTION HAS NO PARAMETERS, which isn't true, since it does, they are just omitted.

Here is my basis code:

/* sample.c - build into sample. */
#include <stdio.h>

int main(void)
{
    int _argc = *((int *)2686800);
    char ***_pargv = (char ***)2686804;
    int i;

    for (i = 1; i < _argc; ++i) {
        printf("%s ", (*_pargv)[i]);
    }

    return 0;
}

./sample I clearly have arguments

The function clearly has arguments passed to it, despite going out of the way to explicitly say that it doesn't by typing void into the function prototype.

As eq- says above:

(6.7.6.3p10) The special case of an unnamed parameter of type void as the only item in the list specifies that the function has no parameters.

Thus saying that the function has void as an argument but actually having arguments on the stack is a contradiction.

My point is that arguments are still there, so explicitly asserting that main is void of arguments is dishonest. The honest way would be to say int main(), which claims nothing about how many parameters it has, only how many parameters you are care about.

NOTE2: The _argc, _pargv are system dependent, to find your values you must find them out by running this program:

/* findargs.c */
#include <stdio.h>

int main(int argc, char **argv)
{
    printf("address of argc is %u.\n", &argc);
    printf("address of argv is %u.\n", &argv);

    return 0;
}

These values should remain correct for your specific system.

Midsummer answered 24/3, 2016 at 2:47 Comment(0)
M
0

In C++, there is no difference between int main() and int main(void).
But in C they are little bit different.
int main() indicates that the main function can be called with any number of parameters or without any parameter. On the other hand, int main(void) indicates that the main function will be called without any parameter

#include <stdio.h> 
int main() 
{ 
    static int i = 5; 
    if (--i){ 
        printf("%d ", i); 
        main(10); 
    } 
}

Output: 4 3 2 1

#include <stdio.h> 
int main(void) 
{ 
    static int i = 5; 
    if (--i){ 
        printf("%d ", i); 
        main(10); 
    } 
} 

It will show error. Because, in int main(void) parameter is void but in the program we have taken main(10) (which defines some value, not void)

Michelemichelina answered 21/11, 2020 at 19:44 Comment(0)
P
0

Technically, if your host is partially POSIX compliant, then you have

int main(); // this legacy is always used by the run time library
int main(int argc); // illegal by compiler
int main(int argc, char** argv); // required by C standards
int main(int argc, char** argv, char** envp); // required by POSIX standard

If you have a Mac, there is also this

int main(int argc, char** argv, char** envp, char** apple); // required by Macintosh standard

Your host will send all the arguments, so a host will always send argc, argv, and envp (and apple if you are using an Apple product), but the programmer could have their main declared as taking void. The implicit function pointer typecast is technically an undefined behavior.

To prevent the typecast undefined behavior, int main() is a neutral form that means it could take any fixed number of arguments using canonical type promotion (int or larger, and double or larger) and int main(int argc, ...) means it could take any variable number of arguments also with canonical type promotion. In other words, the form return_type function_name() is an exception to undefined behavior.

Peeress answered 30/11, 2021 at 5:24 Comment(0)
D
0

In C++:
ㅤㅤint main() and int main(void) are the same in C++. They both take 0 and only 0 parameters.

In C:
ㅤㅤint main() takes as many arguments as you want. The function just won't use them. intㅤㅤㅤ main(void) makes it so passing an argument will create an error and make it impossible to ㅤㅤpass arguments.

Drunkometer answered 29/3, 2022 at 18:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.