Summarizing comments and bits and pieces so they're in one place.
A C program always has an exit code, which the program may decide for itself if it terminates normally, by returning a value from the main
function or by calling the exit
function. If the program terminates abnormally, for example by a segmentation fault, the operating system decides the exit code.
In Unix (Posix), the exit code is an 8-bit value: 0-255. It is combined with some other metadata to a status: the other metadata includes information about whether the program terminated normally or not, if it was terminated because of a signal, and if so, which signal. For details, see the wait(2) manual page.
In Unix, at the shell, the status of the previous command is accessible as the $?
special variable. Because the exit code is only 8 bits, and it's treated as an unsigned integer, if you return a negative value, it gets turned into a positive one: -1 becomes 255. Likewise, if you return a value greater than 255 only the least significant 8 bits are used: 256 becomes 0.
The return type of main
is int
, rather than short
or char
, because there's no particular benefit in making it a smaller type, particularly at this point in history, decades after it was decided. Changing it now would only cause unnecessary complications.
If you want to execute a program from C, the standard library provides the system
function, which handily returns the status of the program. (Note that system
runs commands via the shell, and you need to be very careful about escaping everything correctly if you give the command any externally provided filenames or other things on the command line.)
For more flexibility, you can execute other programs using the system calls fork
, execl
(or one of its variants, see the exec(3) manual page), and wait
(already mentioned above). This is powerful and flexible, but it's also easy to make mistakes, so be sure to read the documentation and check out some example programs first. (On the other hand, it's very much fun to learn this stuff.)
short
overint
unless you have a lot of them in the same place (array or struct). It's not faster to have ashort
and on modern ABIs you often don't even save space by choosing it. In some placesshort
is slower because you have to do sign extension when loading it. – Dietrich Epp