The main function
Every complete executable program requires at least one function, called main, which is where execution begins. You do not have to explicitly declare main, though GNU C permits you to do so. Conventionally, main should be defined to follow one of these calling conventions:
int main (void) {…}
int main (int argc, char *argv[]) {…}
int main (int argc, char *argv[], char *envp[]) {…}
Using void as the parameter list means that main does not use the arguments. You can write char **argv
instead of char *argv[]
, and likewise for envp, as the two constructs are equivalent.
You can call main from C code, as you can call any other function, though that is an unusual thing to do. When you do that, you must write the call to pass arguments that match the parameters in the definition of main.
The main function is not actually the first code that runs when a program starts. In fact, the first code that runs is system code from the file crt0.o. In Unix, this was hand-written assembler code, but in GNU we replaced it with C code. Its job is to find the arguments for main and call that.
Accessing Environment Variables
You can optionally include a third parameter to main, another array of strings, to capture the environment variables available to the program. Unlike what happens with argv, there is no additional parameter for the count of environment variables; rather, the array of environment variables concludes with a null pointer.
#include <stdio.h> /* Declares printf. */
int
main (int argc, char *argv[], char *envp[])
{
/* Print out all environment variables. */
int i = 0;
while (envp[i])
{
printf ("%s\n", envp[i]);
i++;
}
}
Another method of retrieving environment variables is to use the library function getenv, which is defined in stdlib.h. Using getenv does not require defining main to accept the envp pointer. For example, here is a program that fetches and prints the user’s home directory (if defined):
#include <stdlib.h> /* Declares getenv. */
#include <stdio.h> /* Declares printf. */
int
main (void)
{
char *home_directory = getenv ("HOME");
if (home_directory)
printf ("My home directory is: %s\n", home_directory);
else
printf ("My home directory is not defined!\n");
}
Returning Values from main
When main returns, the process terminates. Whatever value main returns becomes the exit status which is reported to the parent process. While nominally the return value is of type int, in fact the exit status gets truncated to eight bits; if main returns the value 256, the exit status is 0.
Normally, programs return only one of two values: 0 for success, and 1 for failure. For maximum portability, use the macro values EXIT_SUCCESS and EXIT_FAILURE defined in stdlib.h. Here’s an example:
#include <stdlib.h> /* Defines EXIT_SUCCESS */
/* and EXIT_FAILURE. */
int
main (void)
{
…
if (foo)
return EXIT_SUCCESS;
else
return EXIT_FAILURE;
}
Some types of programs maintain special conventions for various return values; for example, comparison programs including cmp and diff return 1 to indicate a mismatch, and 2 to indicate that the comparison couldn’t be performed.
Accessing Command-Line Parameters
If the program was invoked with any command-line arguments, it can access them through the arguments of main, argc and argv. (You can give these arguments any names, but the names argc and argv are customary.)
The value of argv is an array containing all of the command-line arguments as strings, with the name of the command invoked as the first string. argc is an integer that says how many strings argv contains. Here is an example of accessing the command-line parameters, retrieving the program’s name and checking for the standard —version and —help options:
#include <string.h> /* Declare strcmp. */
int
main (int argc, char *argv[])
{
char *program_name = argv[0];
for (int i = 1; i < argc; i++)
{
if (!strcmp (argv[i], "--version"))
{
/* Print version information and exit. */
…
}
else if (!strcmp (argv[i], "--help"))
{
/* Print help information and exit. */
…
}
}
…
}