Program Startup--the main Function

A special function called main is the entry point to all C++ programs. This function is not predefined by the compiler; rather, it must be supplied in the program text. The declaration syntax for main is as follows:

int main();

or, optionally:

int main(int argc[[, char *argv[] [[, char *envp[] ]] ]] );

Alternatively, the main function can be declared as returning void (no return value). If you declare main as returning void, you cannot return an exit code to the parent process or operating system using a return statement; to return an exit code when main is declared as void, you must use the exit function.

Argument Definitions

The arguments in the prototype

int main(int argc[[, char *argv[] [[, char *envp[] ]] ]] );

allow convenient command-line parsing of arguments and, optionally, access to environment variables. The argument definitions are as follows:

argc

An integer that contains the count of arguments that follow in argv. The argc parameter is always greater than or equal to 1.

argv

An array of null-terminated strings representing command-line arguments entered by the user of the program. By convention, argv[0] is the command with which the program is invoked, argv[1] is the first command-line argument, and so on, until argv[argc], which is always NULL.

The first command-line argument is always argv[1] and the last one is argv[argc 1].

envp

(Microsoft specific.) The envp array, which is a common extension in many UNIX systems, is used in Microsoft C++. It is an array of strings representing the variables set in the user's environment. This array is terminated by a NULL entry.

The following example shows how to use the argc, argv, and envp arguments to main:

/* Program to type out the environment variables.

* If the /n command-line option is specified,

* the listing of environment variables is line-

* numbered.

*/

#include <iostream.h>

#include <string.h>

#define NL "\n"

int main( int argc, char *argv[], char *envp[] )

{

int iNumberLines = 0; // Default is no line numbers.

// If more than .EXE filename supplied, and

// user supplies /n or /N, flag option for line numbers.

if( argc == 2 && stricmp( argv[1], "/n" ) == 0 )

iNumberLines = 1;

// Walk through list of strings until a NULL is encountered.

for( int i = 0; envp[i] != NULL; ++i )

{

if( iNumberLines )

cout << i;

cout << ": " << envp[i] << NL;

}

return 0;

}

Note:

The return 0 statement at the end of the program is necessary because main is a function declared as returning an int value. If no return statement is present, or if the return statement does not specify a value, an error message is generated.

Wildcard Expansion (Microsoft Specific)

You can use wildcards—the question mark (?) and asterisk (*)—to specify filename and path arguments on the command line.

Command-line arguments are handled by a routine called _setargv. By default, _setargv does not expand wildcards into separate strings in the argv string array. However, by linking with the SETARGV.OBJ file, you can replace the default _setargv routine with a version that handles wildcards.

To include SETARGV.OBJ, either add it to your project in PWB, or specify it on the CL command line. In either case, the /NOE (no extended dictionary search) must be supplied to the linker to avoid multiple-definition errors for the _setargv function. A sample CL command follows:

CL PROG.C \C7\LIB\SETARGV.OBJ /LINK /NOE;

The result of the preceding command is that wildcard filenames are expanded in the same manner as MS-DOS commands. (See your MS-DOS user's guide if you are unfamiliar with these characters.) Enclosing a command-line argument in quotation marks (" ") suppresses the wildcard expansion. Within quoted arguments, you can represent quotation marks literally by preceding the double quotation mark with a backslash (\).

Note:

If you write your own _setargv function, it must be specified as extern "C" for the linker to recognize it.

If no matches are found for the wildcard argument, the argument is passed literally.

Parsing Command-Line Arguments (Microsoft Specific)

Microsoft C startup code uses the following rules when interpreting arguments given on the MS-DOS command line:

Arguments are delimited by white space, which is either a space or a tab.

The caret character (^) is not recognized as an escape character or delimiter. The character is handled completely by the command-line parser in the operating system before being passed to the argv array in the program.

A string surrounded by double quotation marks ("string") is interpreted as a single argument, regardless of white space contained within. A quoted string can be embedded in an argument.

A double quotation mark preceded by a backslash (\") is interpreted as a literal double quotation mark character (").

Backslashes are interpreted literally, unless they immediately precede a double quotation mark.

If an even number of backslashes is followed by a double quotation mark, then one backslash is placed in the argv array for every pair of backslashes, and the double quotation mark is interpreted as a string delimiter.

If an odd number of backslashes is followed by a double quotation mark, then one backslash is placed in the argv array for every pair of backslashes, and the double quotation mark is “escaped” by the remaining backslash, causing a literal double quotation mark (") to be placed in argv.

The following program demonstrates how command-line arguments are passed:

#include <iostream.h>

int main( int argc, // Number of strings in array argv

char *argv[], // Array of command-line argument strings

char *envp[] ) // Array of environment variable strings

{

int count;

// Display each command-line argument.

cout << "\nCommand-line arguments:\n";

for( count = 0; count < argc; count++ )

cout << " argv[" << count << "] "

<< argv[count] << "\n";

return 0;

}

Table 2.2 shows example input and expected output, demonstrating the rules in the preceding list.

Table 2.2 Results of Parsing Command Lines

Command-Line Input argv[1] argv[2] argv[3]

"abc"de abc d e
a\\\b d"e f"g h a\\\b de fg, h  
a\\\"b c d a\"b c d
a\\\\"b c" d e a\\b c d e

Customizing Command-Line Processing (Microsoft Specific)

If your program does not take command-line arguments, you can save a small amount of space by suppressing use of the library routine that performs command-line processing. This routine is called _setargv and is described in “Wildcard Expansion”. To suppress its use, define a routine that does nothing in the file containing the main function, and name it _setargv. The call to _setargv is then satisfied by your definition of _setargv, and the library version is not loaded.

Similarly, if you never access the environment table through the envp argument, you can provide your own empty routine to be used in place of _setenvp, the environment-processing routine. Just as with the _setargv function, _setenvp must be declared as extern "C".

Your program might make calls to the spawn or exec family of routines in the C run-time library. If this is the case, you should not suppress the environmentprocessing routine, since this routine is used to pass an environment from the parent process to the child process.

main Function Restrictions

Several restrictions apply to the main function that do not apply to any other C++ functions. The main function:

Cannot be overloaded (See Chapter 12, “Overloading”).

Cannot be declared as inline.

Cannot be declared as static.

Cannot have its address taken.

Cannot be called.