The reason why main returns an int instead of being void is because it needs to report its exit status back to its parent process. For a more complete explanation, the Wikipedia article is at http://en.wikipedia.org/wiki/Exit_code
Programmers will normally only see this returned status code when writing perl scripts, shell scripts, or batch files. When called, your program might work normally or it might not be able to because of some error condition; eg, it couldn't find a file it was supposed to open and process, it received the number and types of command-line arguments. The script that called that program needs to know whether it did what it was supposed to or if it failed, so that the script can then decide what to do next. Conceptually, that is no different from having a function return a special value to indicate failure (eg, if fopen succeeds in opening the file, it returns the FILE pointer, but if it fails then it returns NULL; other functions that return an int will customarily return -1 in case of failure).
The convention that is followed in scripts is that if the program returns zero, then it succeeded. Any non-zero value means failure and the abundance of choices allows the programmer to define a set of error codes to specify exactly what kind of error caused the abnormal termination of the program. There is no standard for specific error code values, so every program is free to define its own, which means that the script writer will need to read the function's documentation if he wants to detect and handle specific types of errors.
The convention is for the last statement in the main function to be return 0;
. Within main, you can return error conditions with other return statements (eg, return 2;
), but if you are in another function when you decide to terminate abnormally then return would only take you back to the calling function, not terminate the program. For that, we have the exit(int status);
function, which can be called from anywhere in the program and does not return because it immediate terminates the program with the status code that you pass to it. Common practice is to use return 0 to terminate normally at the end of main and exit everywhere else for abnormal termination.
As for conio, that is more a judgement call that touches on a goal in C programming: portability. If a C program is portable, that means that you can take the source code and compile and run it on any other system. Most high-level programs can be portable, but any program that uses features specific to the operating system loses its portability.
That's not completely black-and-white in that some non-portable programs are more non-portable than others and this can affect how a programmer will organize his program. One programming task is to take a program on one platform (refering to the computer itself and the operating system) and porting
it to another platform -- read Wikipedia at http://en.wikipedia.org/wiki/Porting
. Porting involves finding the non-portable elements of the code and rewriting them to do the same thing on the target platform. Of course, some programs are harder to port than others because of how the original programmer had organized his code. If he sprinkled the non-portable elements throughout the code, then it can be a nightmare for the programmer who has to port it. But if he collected all the non-portable elements in one or a few places, usually within wrapper functions
) to be called from the standard parts of the code, then that makes the porting process much easier and more fool-proof, since the porting programmer would only need to change those few files. One of the more famous stories of successful porting is UNIX, which was co-developed with C circa 1970. Traditionally, operating systems were written in assembly, which is most highly non-portable, so porting an operating system meant having to rewrite it completely almost from scratch. But the UNIX kernel was written in C, so almost all you needed to do to port it was to install a C compiler on the target system and recompile the kernel. The most non-portable part, the low-level code that dealt with the hardware, was contained mainly in the drivers which the kernel would call, so most of the work in porting UNIX was in rewriting the drivers, a much easier task than rewriting the entire kernel. And in porting the C compiler, which I would assume was organized to facilitate porting.
conio ("Console I/O") is an MS-DOS library (read http://en.wikipedia.org/wiki/Conio
). It was written for MS-DOS compilers and used either MS-DOS system and BIOS calls or intimate knowledge of BIOS and RAM usage. It is highly specific to MS-DOS and does not exist in any other operating system except as a port. As such, it is not portable
. Though to be fair, what it does is also not portable, with different operating systems handling those low-level functions differently.
So it becomes a judgement call. conio is there for quick-and-dirty applications and to get started, but there are other ways that you also need to learn, so you mustn't become overly dependent on conio.
But more specific to your program, instead of getch you should use getchar, which is in the standard library.