Still, I'm not aware of any implementation that explicitly supported void as the return type of main. (Many compilers would accept just about any return type without complaint.)
Somehow some authors got the idea that "void main()" was a good idea. I find it to be a good way to detect authors who don't know the language very well.
It seems like a bad idea to use void return type (presumably you want the program to always return 0), but the standard permits it.
edit Wikipedia seems less convinced that it's ok [1]
You can't just make up extra signatures for main and expect your compiler to deal with them. Of course, if your compiler vendor says that a particular non-standard signature is available, you're free to use it.
Put another way, C doesn't let you get away with the try it and see approach the way many other languages do.
Exactly, and I don't see any upside to this "tradeoff". It seems strictly worse, but maybe I'm missing something.
More generally it's because the C language standard is steered only partly by the interests of C programmers: 1) the C standard aims to easily support many different platforms and compilers, 2) it aims to remain a compact and stable (slowly changing) language, and 3) it aims for maximal performance. None of those 3 aligns with programmer convenience.
Point 1 ties in to the origins of the C standard itself, which was deliberately designed not to nail down every last detail. This was to incorporate different compilers and platforms. e.g. Where Java mandates two's complement, C doesn't. C was carefully designed so that platforms that don't use two's complement, don't have to jump through (many) hoops in order to comply with the standard. Neither should they be tempted to just break the standard for their own convenience/performance.
Point 2 means there's tremendous inertia in the C language. There are considerable upsides to the language being slow to change, though. Although mistakes in the language are slower to be fixed, they're also much less likely to make it into the standard in the first place, compared to a fast-moving language like D. It's also a tremendous advantage for compiler engineers - they can spend their time improving their compiler rather than keeping up with the standard.
(Related trivia: C++20 will break with tradition and mandate two's complement for signed integer types. I don't think C will do this though.)
And finally Point 3. C's weird and wonderful rules on undefined behaviour permit compilers to make strange optimisations and to omit runtime checks, but they require the programmer to have an eagle eye, and undefined behaviour can manifest in peculiar ways that are hard to hunt down. There are endless horror stories of bizarre undefined behaviour.
That said, I'm not sure that performance (on modern platforms) is really such a factor in C's quirks. I believe that these days (with modern compilers), C's performance is generally about the same as that of other similar languages that lack broad undefined behaviour, such as Ada.
Honourable mention: in at least one instance, undefined behaviour was deliberately introduced into the standard to permit trap-based error-reporting that was convenient on one particular hardware platform. [0] (Previously the relevant action would merely produce an indeterminate value.) I believe this unusual though even for C.
[0] http://blog.frama-c.com/index.php?post/2013/03/13/indetermin... (ctrl-f for Itanium)
However, in the specific context of stand-alone or freestanding programs, the "void main()" definition would be absolutely nonconsequential, since there is no host to return a value to.
One possible consequence I can think of: If your program is safety-critical (or even otherwise) you might be interested in running static analysis or verification tools on it. These tools implement the C standard, so they would emit a diagnostic on the use of void main.
Other than that, sure, the language police will not come and break down your door. If your compiler's docs say that it accepts this construct with the meaning you want, it is indeed an inconsequential, though also completely unnecessary, deviation from the standard.
For hosted implementations, "void main()" might be valid, but "int main(void)" is always valid.
A tutorial should not suggest "void main()" without mentioning any of this.
Reference: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf sections 5.1.2.1 (freestanding environments) and 5.1.2.2.1 (hosted environments).
FWIW, I learned "ANSI C" from a book older than 1989. I've written C programs that ran on 8-bit to 64-bit machines, big- and little-endian, on a dozen OSs (most of which no longer exist), and even no OS. I've never even heard of this being a problem.
The C standard specifies (for hosted implementations) two ways to define "main", and allows implementations to document and support more. "int main(void)" is one of them. "int main()" is not. So, strictly speaking, using "int main()" makes your program's behavior undefined.
On the other hand, as far as I know every implementation actually allows "int main()" with no problem. This was necessary to support pre-ANSI C code, which couldn't use the "void" keyword. It's still better to be explicit and use "int main(void)" rather than "int main()". (It can also affect recursive calls to main, which are legal but almost certainly a bad idea.)
These kinds of problems might not happen with common ABIs, but if you try to write C on the assumption that it will be compiled in a reasonable way based on your knowledge of how the plaform works, then modern compilers will punish you for your presumption.
Which is really a bug that everyone has decided to look the other way around because it wins compiler benchmarks despite coming against what C originally was meant for.
Specifically (from the C89 rationale[0], that i'm certain most people who think those benchmarks are good haven't read):
> C code can be non-portable. Although it strove to give programmers the opportunity to write truly portable programs, the Committee did not want to force programmers into writing portably, to preclude the use of C as a ``high-level assembler'': the ability to write machine-specific code is one of the strengths of C. It is this principle which largely motivates drawing the distinction between strictly conforming program and conforming program (§1.7).
Also in the same rationale it mentions how "the spirit of C" is to do operations in the way the machine would do it instead of forcing some abstract rule - yet that exactly is what happens later when everyone goes all language lawyer about C's abstract machine and how you should not rely on what you think the target machine would do.
Since this comment is getting downvotes, I'll explain. The "void" keyword was introduced in the 1989 ANSI C standard. That same standard specified that the valid definitions for the main functions are:
and or equivalent (or implementations can support other forms). There has never been a version of C in which "void main()" is a valid way to define the main function.It's a small detail, and yes, many compilers will let you get away with it (the language doesn't require a diagnostic), but anyone writing about C should be aware of this, and should set a good example by writing correct code.
Maybe the site is OK other than that, but it doesn't inspire confidence.