Why has setting the entry point's return type to void in C++ always been discouraged, and was later removed by the standard and is prohibited by modern compilers? Why is it considered bad practice?
Now, as I understand C# and Java both allow the entry point's return type to be void i.e
static void main(String[] args) /* Java */
static void Main(string[] args) /* C# */
And C# and Java programmers do not consider it bad practice, they use it often in fact.
Other languages which are (only intended to be, I doubt C++ will be succeeded in this decade, at least) possible successors of C++ like the D Programming Language or Vala also allow a void main(). So as you can see, I doubt the C++ community removed it from the standard because it was too obscure or unpopular.
So my question is, Why did the C++ Community Remove void main()? What was wrong with it?
The C++ standards committee likely chose to require int main() because of the large body of existing code that expected to use a return statement to return a specific exit code to the runtime system. It would be unreasonable to expect all existing code to change to use exit() instead, so int main() was made a requirement in the standard.
A language such as Java, when it was designed, did not have any body of existing code that it needed to remain compatible with. Therefore, the designers could choose void main() and require the use of System.exit() for non-zero exit codes.
So, the thing that would be "wrong" with choosing void main() for the C++ standard would be that it would break existing code that expected to use return and an exit code value from main().
C++ has never permitted void main(), though some compilers might permit it either as an extension or just because they don't diagnose it.
Similarly C has never permitted void main() other than as an extension; the same 1989 standard that introduced the void keyword defined the two standard definitions for main: int main(void) and int main(int argc, char *argv[]).
Other languages permit it because, well, they're other languages.
There is no particular advantage in being able to write void main() rather than int main(). You don't even need to explicitly return a value; falling off the end of main is equivalent to return 0; (in C++, and in C starting with C99).
You generally want to know the exit status of your program. That's the reason why you have the int main() -- you return your exit status.
It's wrong because this is not what the C++ Standard specifies as a legal main. Nobody cares about what the other languages specify. For C++ programs, only the C++ Standard is relevant, and it says int.
Related
I have below discovery by chance. The compiler compiles the below code without any error or warning. Please help me understand why the compiler is not throwing any error? The program contains just a string in a double quotation.
I have not declared any char array neither assigned the below string to any variable.
void main()
{
"Why there is no error in compilation?";
}
Because any expression is a valid statement.
"Why is there no error in compilation?";
is a statement that consists of an expression that evaluates to the given literal string. This is a perfectly valid statement that happens to have no effect whatsoever.
Of course, "useful" statements look more like
a = b;
But well;
b;
is also a valid statement. In your case, b is simply string literal; and you are free to place that within a the body of a method. Obviously this statement doesn't have any side effects; but what if the statement would be something like
"some string " + someFunctionReturningString();
You probably would want that expression to be executed; and as side effect, that method to be called, wouldn't you?
Compile the program with -Wunused-value flag. It just raises
warning: statement with no effect
"Why there is no error in compilation?";
^
That is it.
And If you compile the above code with -Wall flag it also says
warning: return type of ‘main’ is not ‘int’ [-Wmain]
void main() {
void main()
{
"Why there is no error in compilation?";
}
First, let's address the string literal. An expression statement, which is valid in any context where any statement is valid, consists of an (optional) expression followed by a semicolon. The expression is evaluated and any result is discarded. (The empty statement, consisting of just a semicolon, is classified as an expression statement; I'm not sure why.)
Expression statements are very common, but usually used when the expression has side effects. For example, both assignments (x = 42;) and function calls (printf("Hello, world\n")) are expressions, and the both yield values. If you don't care about the result, just add a semicolon and you have a valid statement.
Not all expressions have side effects. Adding a semicolon to an expression that doesn't have any side effects, as you've done here (a string literal is an expression), is not generally useful, but the language doesn't forbid it. Generally C lets you do what you want and lets you worry about whether it makes sense, rather than imposing special-case rules that might prevent mistakes but could also prevent you from doing something useful.
Now let's cover void main(). A lot of people will tell you, with some justification, that this is wrong, and that the correct definition is int main(void). That's almost correct, and it's excellent advice, but the details are more complicated than that.
For a hosted implementation (basically one that provides the standard library), main may be defined in one of three ways:
int main(void) { /* ... */ }
or
int main(int argc, char *argv[]) { /* ... */ }
or equivalent, "or in some other implementation-defined manner." (See N1570 section 5.1.2.2.2 for the gory details.) That means that a particular implementation is permitted to document and implement forms of main other than the two mandated forms. In particular, a compiler can (and some do) state in its documentation that
void main() { /* ... */ }
and/or
void main(void) { /* ... */ }
is valid for that compiler. And a compiler that doesn't explicitly support void main() isn't required to complain if you write void main() anyway. It's not a syntax error or a constraint violation; it just has undefined behavior.
For a freestanding implementation (basically one that targets embedded systems with no OS, and no requirement to support most of the standard library), the entry point is entirely implementation-defined; it needn't even be called main. Requiring void main() is not uncommon for such implementations. (You're probably using a hosted implementation.)
Having said all that, if you're using a hosted implementation, you should always define main with an int return type (and in C you should int main(void) rather than int main()). There is no good reason to use void main(). It makes your program non-portable, and it causes annoying pedants like me to bore you with lengthy discussions of how main should be defined.
A number of C books advise you to use void main(). If you see this, remember who wrote the book and avoid anything written by that author; he or she doesn't know C very well, and will likely make other mistakes. (I'm thinking of Herbert Schildt in particular.) The great irony here is that void keyword was introduced by the 1989 ANSI C standard -- the very same standard that introduced the requirement for main to return int (unless the implementation explicitly permits something else).
I've discussed the C rules so far. Your question is tagged both C and C++, and the rules are a bit different in C++. In C++, empty parentheses on a function declaration or definition have a different meaning, and you should write int main() rather than int main(void) (the latter is supported in C++, but only for compatibility with C). And C++ requires main to return int for hosted implementations, with no permission for an implementation to support void main().
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 7 years ago.
Improve this question
I understand C and C++ are different languages but when I was learning C++ I was always told that C is a subset of C++ or C++ is C with classes. And that was quiet true until the appearance of C++x0, C++11 (or the modern C++ 11/14/17 in general). In fact (specially when working on embedded systems) it's very likely to find code written in C++ but with a lot of parts written entirely in pure C language. Here I have several questions:
Should I stop using the term C/C++?
If the answer to #1 is yes, how would I call a program that use a mix of C and C++?
Given that both of them are 'different' languages is it likely that at some point C++ compilers stop supporting code written in the C language (since modern c++ is diverging from the C mentality for basic stuff like pointers, dynamic memory handling, etc)
Is there right now any collaboration between the people who makes the standards of C/C++ to keep the compatibility
If #4 is yes, such collaboration could end up in the near future with the appearance of the modern c++ (11/14/17)
I know that there already similar questions, but I'm sure that a lot of people share these doubts so I'm very interested to get good answers specially for the points that have to do with the C++ tendency in the near future.
C was never a subset of C++. The most obvious example of this is int new;. This has been true since C89 and C++98, and the languages have only grown further from each other as new standards have come out.
Should I stop using the term C/C++
Yes
If the answer to #1 is yes, how would I call a program that use a mix of C and C++?
A source file is written in one language or the other. A program can consist of code from multiple languages working together, or an executable produced by linking different compiled objects. You would say the program was written in C and C++, "C/C++" is not a language.
Given that both of them are 'different' languages is it likely that at some point C++ compilers stop supporting code written in the C language
3) They never did. int *a = malloc(10);. C and C++ have long since diverged. click the links or see below for a file that is fine with C89 and up, but isn't valid under any C++ standard.
4) afaik no, the working groups are aware of each other but the standards make the decisions that are best for themselves.
/* A bunch of code that compiles and runs under C89 but fails under any C++ */
/* type aliases and struct names occupy separate namespaces in C, not in C++ */
struct S { int i; };
typedef int S;
struct Outer { struct Inner { int i; } in; };
/* struct Inner will be Outer::Inner in C++ due to name scope */
struct Inner inner;
/* default return type of int in C, C++ functions need explicit return types */
g() {
return 0;
}
/* C sees this as two declarations of the same integer,
* C++ sees it as redefinition */
int n;
int n;
/* K&R style argument type declarations */
void h(i) int i; { }
/* struct type declaration in return type */
struct S2{int a;} j(void) { struct S2 s = {1}; return s; }
/* struct type declaration in argument, stupid and useless, but valid */
/*void dumb(struct S3{int a;} s) { } */
/* enum/int assignment */
enum E{A, B};
enum E e = 1;
void k() {
goto label; /* C allows jumping past an initialization */
{
int x = 0;
label:
x = 1;
}
}
/* () in declaration means unspecified number of arguments in C, the definition
* can take any number of arguments,
* but means the same as (void) in C++ (definition below main) */
void f();
int main(void) {
f(1); /* doesn't match declaration in C++ */
{
/* new is a keyword in C++ */
int new = 0;
}
/* no stdio.h include results in implicit definiton in C. However,
* as long as a matching function is found at link-time, it's fine.
* C++ requires a declaration for all called functions */
puts("C is not C++");
{
int *ip;
void *vp = 0;
ip = vp; /* cast required in C++, not in C */
}
return 0;
}
/* matches declaration in C, not in C++ */
void f(int i) { }
I always feel it's worth mentioning that C is a subset of Objective-C.
I was always told that C is a subset of C++ or C++ is C with classes. And that was quiet true until the appearance of C++x0, C++11 (or the modern C++ 11/14/17 in general).
C has never been a subset of C++. For example C89 is not a subset of C++98.
A few examples:
the C89 identifier-list form for function parameter declaration is not supported in C++
C89 and C++98 have different types for the characters constants
C89 and C++98 have different types for string literals
logical operators yield different types in C89 and C++98 (int vs bool)
Should I stop using the term C/C++?
Yes.
If the answer to #1 is yes, how would I call a program that use a mix of C and C++?
A program is either C or C++ (if even some very basic program can compiled with either a C or a C++ compiler). What compiler are you using to compile it? It should answer your question. Harbison & Steele coined the term Clean C to designate a common subset of C and C++ but I think it was a bad idea.
EDIT: However I admit that technically you can link C and C++ objects files in a single program but OTH there are many languages that are allowed to be mixed in a single program for example Java and C++. I think using the term C/C++ program only adds to the confusion that it is written in a single language called C/C++.
Given that both of them are 'different' languages is it likely that at some point C++ compilers stop supporting code written in the C language (since modern c++ is diverging from the C mentality for basic stuff like pointers, dynamic memory handling, etc)
There are many features (example: variable length array, flexible array member, _Generic, ...) of C99 or C11 that are not supported by any C++ version.
In general the SO users ask the person who is asking the question to choose a language: C or C++. Why?
There are many subtle differences between C and C++. For example, in C++, a const variable at global scope has internal linkage unless declared extern, but in C it has external linkage unless declared static. By saying "C/C++", the OP is asserting knowledge that the answer to their question is the same in both C and C++, when it very well might not be. This needlessly makes things harder for would-be answerers.
Sometimes we can spot that the code isn't valid in one language or the other (for example, implicit conversions from void* to pointer to object are not valid in C++). This is annoying. Why are you saying "C/C++" when you have a piece of code that's valid in C but not C++? Did you intend C, or is this just an error in code intended to be C++?
Sometimes the answer will be different depending on the language (for example, variable-length arrays exist in C99 but not in C++). If we don't know what language you're talking about, either we have to guess, or write an answer for both when only one will actually be useful, because you know which language you're actually using; you're just not telling us!
Sometimes the answer really is the same for both languages, but it's hard to be sure. For example, I think C and C++ have the same integer conversion rules, but in order to be really, really sure, I have to read both standards carefully. Again, this makes me do twice as much work as necessary when you probably only care about one of the languages.
Anyway, to answer your other questions:
Yes.
If you are linking together C and C++ code, it is acceptable to use both tags, but please specify which language each file is in.
There are breaking changes sometimes, but they're rare and typically limited in impact (otherwise they don't get approved). For example, auto in C++11.
I don't think they directly collaborate, but they pay attention to developments in the other language and try to avoid introducing changes that would make compatibility more difficult.
And if you really do want to know about both languages, that's fine, and you can say that in your question. When you say "C/C++", I'm really not sure what you mean, and it really looks like you're making an assumption about the two languages.
Often times I see the infamous void main() around the forums and almost immediately a comment following the question telling the user to never use void main() (which I am in complete agreement with). But where is the origin of void main()?
Why am I still seeing newer people pick up the bad habit of having main return nothing when the proper way is to return an int.
I understand WHY this method is wrong as explained in this question and multitudes of others, but I don't how this method of declaring main came about or even why it is still taught to some students.
Even Bjarne Stroustrup has written void main, in C++, so it's indeed a common anti-meme, and an old one, predating Java and other contemporary languages that support void main. Of course Bjarne has also written that void main has never been part of either C or C++. However, for this latter statement (in his FAQ), at least as of C99 it looks as if Bjarne is wrong, because the N869 draft of the C99 standard says in its §5.1.2.2.3/1 that
“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.”
And earlier, in its §5.1.2.2.1/1 it states about the signature of main,
“ or in some other implementation-defined manner.”
A return type “not compatible with int” could, for example, be void.
So, while this is not a complete answer (I doubt that historical sources about this are available on the net), at least it goes some way towards correcting the assumptions of the question. It is not the case that void main is a complete abomination in C and C++. But in C++ it's invalid: it's a C thing that's not supported in a hosted C++ implementation.
I have been a victim of this problem, so I think I can tell you why this happens, During our C lectures the faculties have to start our lectures using a sample program (probably "Hello World") and for that they have to use main() method.
But since they don't want to confuse students and also they don't want to get into the complexity of teaching the return types and return statements at the very start of their C programming lessons, they use(and also ask us to use) void main() and tell us to assume this as the default type till we study functions and return types in detail.
Hence this leads to develop a wrong habit of using void main() from the very first lecture of our C-Programming.
Hope that explains u well about why most of the Computer Programmers especially the newer ones pick up this bad practice.
Cheers,
Mayank
Personally I think it's the following: K&R C didn't require to specify a return type and implicitly assumed it to be int and at the same time the examples in K&R didn't use a return value.
For example the first code in K&R first edition is the following:
#include <stdio.h>
main()
{
printf("Hello World\n");
}
So it's no wonder that people reading this later (after a void type was added to the language as an extension by some compilers) assumed that main actually had a void return statement.. I would've done the same thing.
Actually K&R does say later:
In the interests of simplicity, we have omitted return statements from
our main functions up to this point, but we will include them
hereafter, as a reminder that programs should return status to their
environment.
So that's just another example of what happens when you write incorrect code and include a disclaimer later under the assumption that people will read everything before doing stupid things ;)
As one author amongst a number of others, Herbert Schildt wrote some popular but not necessarily high quality books which espoused the idea.
One egregious example is his The Annotated C Standard. He quotes the ISO/IEC 9899:1990 standard on left-hand pages and provides annotations on the right-hand pages. When he quotes section 5.1.2.2.1 Program Startup, it says:
The function called at program startup is named main. The implementation declares no prototype for this function. It can be defined with no parameters:
int main(void) { /* ... */ }
or with two parameters (…):
int main(int argc, char *argv[]) { /* ... */ }
This doesn't include the 'or in some other implementation-defined manner' clause that was added to C99.
Then, in the annotations, he says:
Interestingly, there is no prototype for main() declared by the compiler. You are therefore free to declare main() as required by your program. For example, here are three common methods of declaring main():
void main(void) /* no return value, no parameters */
int main(void) /* return a value, no parameters */
/* return a value and include command-line parameters */
int main(int argc, char *argv[])
The first variation is not allowed by the C90 standard, despite what he says, but innocent readers might be confused.
Note that section 5.1.2.2.3 Program termination says:
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. If the main function executes a return that specifies no value, the termination status returned to the hosted environment is undefined.
Since you'd find that exit takes an int argument, it is clear from this that the return type of main should be int.
The commentary says:
In most implementations, the return value from main(), if there is one, is returned to the operating system. Remember, if you don't explicitly return a value from main() then the value passed to the operating system is, technically, undefined. Though most compilers will automatically return 0 when no other return value is specified (even when main() is declared as void), you should not rely on this fact because it is not guaranteed by the standard.
Some of this commentary is so much bovine excrement, a view in which I am not alone in holding. The only merit in the book is that it includes almost all of the C90 standard (there's one page missing from the description of fprintf — the same page got printed twice) for far less than the cost of the standard. It's been argued that the difference in price represents the loss of value from the commentary. See Lysator generally for some information on C, and Clive Feather's review of The Annotated C Standard.
Another of his books is C: The Complete Reference, which made it to at least the 4th Edition. The 3rd Edition used void main() extensively; this may have been cleaned up by the 4th Edition, but it's sad it took that many editions to get such a fundamental issue correct.
Embedded programs that run on bare metal, that is without an operating system, never return. On power up, the reset vector jumps indirectly (there is some memory initialization that happens first) to main and inside of main, there is an infinite while (1){} loop. Semantically, a return value for main doesn't make sense.
Possible reasons:
Java programmers used to writing public static void main(...).
Missing return statement could have some assume main does't return, although it implicitly returns 0.
In C you were able to write main() with no return type, and it would be int by default. Maybe some assume a missing return type is equivalent to a void.
Bad books / teachers?
From a C++ point-of-view, 3 sources of confusion exist:
Fundamentalist PC/desktop programmers who fanatically and blindly preach int main() without actually knowing the complete picture in the standard themselves. C and C++ have completely different rules for how main() should be declared in freestanding systems (when programming bare metal embedded systems or operative systems).
The C language, which historically has had different rules compared with C++. And in C, the rules for main() have changed over time.
Legacy compilers and coding standards from the dark ages, including programming teachers stuck in the 1980s.
I'll address each source of confusion in this answer.
The PC/desktop programmers are problematic since they assume that hosted systems are the only systems existing and therefore spread incorrect/incomplete propaganda about the correct form of main(), dogmatically stating that you must use int main(), incorrectly citing the standard while doing so, if at all.
Both the C and C++ standards has always listed two kinds of systems: freestanding and hosted.
In freestanding implementations, void main (void) has always been allowed in C. In C++, freestanding implementations are slightly different: a freestanding implementation may not name the entry function main() or it has to follow the stated forms that return int.
Not even Bjarne Stroustrup manages to cite the standards or explain this correctly/completely, so no wonder that the average programmer is confused! (He is citing the hosted environment sub-chapter and fails to cite all relevant parts of it).
This is all discussed in detail with references to the standard(s) here, Bjarne and others please read.
Regarding void main (void) in hosted systems, this originates way back, from somewhere in the dark ages before the ISO C standard, where everything was allowed.
I would suspect that the major culprit behind it is the Borland Turbo C compiler, which was already the market leader when ISO C was released in 1990. This compiler allowed void main (void).
And it should be noted that void main (void) for hosted implementations was implicitly forbidden in C90 for hosted systems, no implementation-defined forms were allowed. So Turbo C was never a strictly conforming implementation. Yet it is still used in schools (particularly in India)! Teaching every student incorrect programming standards from scratch.
Since C99, void main (void) and other forms became allowed in C, because of a strange sentence which was added: "or in some other implementation-defined manner". This is also discussed in the linked answer above, with references to the C99 rationale and other parts of the C standard that are assuming that a hosted system main() may not return int.
Therefore in C, void main (void) is (arguably) currently an allowed form for hosted implementations, given that the compiler documents what it does. But note that since this is implementation-defined behavior, it is the compiler that determines whether this form is allowed or not, not the programmer!
In C++, void main (void) is not an allowed form.
I just read a comment that said something along the likes of:
"You should never use void main() you should always use int main()."
Now I know the reasons for using int main() (so that you can check for success on return and whatnot) but I didn't know that using void main() was illegal. I did some investigating and the only reason I could find not use void main() is because the "standard says so".
My question is:
Why, if the C++ standard says that main must return a value, does g++ allow programmers to use void main() as valid syntax? Shouldn't it return an error / warning because it goes against what the standard says?
That only means that a particular version of your compiler may allow it, but the later versions (which is likely to be more Standard conformant) may not allow it. So better write Standard Conformant code from the beginning!
According to the standard, main is indeed required to return int. But many compilers allow a return type of void since in pre-standard C++ it was allowed, and for a long time much code was written with a return type of void.
It is also worth to mention that C++ explicitly allows obission of the return statement for void:
int main() {
}
will return 0. But that is only allowed for main.
You can force the compiler to be standards compliment by using the following the build commands:
-ansi -pedantic -Wall
If you are not coding cross-platform code then -c99 might be a better choice. Not all compilers support that.
The GNU Project has a decent summary of their philosophy:
In most cases, following published standards is convenient for users—it means that their programs or scripts will work more portably. ...
But we do not follow either of these specifications rigidly, and there are specific points on which we decided not to follow them, so as to make the GNU system better for users.
For instance, Standard C says that nearly all extensions to C are prohibited. How silly! GCC implements many extensions, some of which were later adopted as part of the standard. If you want these constructs to give an error message as "required" by the standard, you must specify --pedantic, which was implemented only so that we can say "GCC is a 100% implementation of the standard," not because there is any reason to actually use it.
POSIX.2 specifies that df and du must output sizes by default in units of 512 bytes. What users want is units of 1k, so that is what we do by default. If you want the ridiculous behavior "required" by POSIX, you must set the environment variable POSIXLY_CORRECT (which was originally going to be named POSIX_ME_HARDER). ...
In particular, don’t reject a new feature, or remove an old one, merely because a standard says it is "forbidden" or "deprecated."
Sometimes, GCC has removed extensions when they caused confusion like this one. I believe this extension existed to allow old code with an incorrect main declaration to compile, not necessarily to encourage people writing void main(). Similar to the extension that allowed pre-POSIX function declarations. Besides, while int main(int argc, const char** argv) is the C-approved declaration for main, the C++ standard also sanctions int main(), and POSIX sanctions int main(int argc, const char** argv, const char** envp). There may well be other declarations that I haven't run into yet.
Some C++ compilers allow the main function to have return type void. But doesn't the Operating System require int type value returned to specify whether the program ended well or not?
C++ does not allow main to have a void return type. The published C++ standard requires it to be int. Some C++ compilers allow you to use void, but that's not recommended. In general, the OS doesn't care one way or the other. A specific OS might require a program to give a return value, but it doesn't necessarily have to come from main's return value. If the C++ compiler allows void, then it probably provides some other means of specifying the program's exit code.
C++ allows main function to have return type void
No, it doesn't.
The C++ standard only requires 2 different types of main signatures. Others may be optionally added if the return type is int.
Implementations of C++ which allow void return types are incorrect in terms of the C++ standard.
C++03 standard S. 3.6.1-2:
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() { /* ... */ }
int main(int argc, char* argv[]) {/* ... */ }
If you want portable C++ code, or to write good C++ examples then you should always use one of the 2 variations above.
main returning void is accepted for backwards compatibility, but it is not legal.
In this case, the exit code will be 0. You can still change the exit code, using exit function.
The C++ standard does not allow main() to have a return type of void. Most compilers will let it pass for historical reasons, though.
In languages where a void return from main is legal (not C++), the OS usually sees a return value of 0 on normal (non-exceptional) program termination.
That's why void main() is not allowed by standard C++ - though some compilers (e.g. gcc) does allow it.
To make it short: always use int main(), never void main().
Depending on the compiler, you may be able to use a void main function, however the proper way (that a truly standard compliant compiler should follow) is to return int with 0 being a nice & clean exit and anything else indicating that your program has done something wrong.
But doesn't OS require int type value returned to specify whether program
ended well or not?
Why would it always? On windows when you double click on the icon, the process dies after it ends. OS do not check for the return type there. Even on linux if you just run the binary as ./runBinary, it simply runs and exits. The OS do not show message by itself that it fails or succeeds.
All the above answers are right that the standard says it is int, but some compilers allow void too.