3.3. The main function

C++ programs are made up of functions and every executable program must have exactly one function named main that serves as the entry point for the program. Libraries do not need a main, because they are intended to link with another program that contains a main. Several restrictions apply to the main function that don’t apply to any other C++ functions. The main function:

There are only a few main signatures that are valid entry points:

// if main takes no arguments
int main()

// if main takes command-line arguments
int main(int argc, char* argv[])

The names argc and argv are traditional. You could use any valid identifier, but most programs use these.

  • int argc: the total number of arguments in argv, strings separated by white space (space or tab characters)

  • char *argv[]: an array of these strings

    char *argv[] can also be specified as char **argv, which is the same thing, if you remember pointers from your first semester. If not, we’ll cover it soon.

Some compilers allow passing the current system environment variables as a third argument passed into main. The environment variables are also passed in as an array of C strings.

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

If the linker can’t find a function that evaluates to one of the above, then it will fail and your program build is incomplete.

A simple command line argument handling program. replit.com is a website that provides a variety of compilers online.

Press the “play” button to compile and run the program.

Replit provides an interactive shell. You can run this program manually in the shell by typing

./main

Another convention is to store the name of the program as invoked on the command line in argv[0]. One side effect of this is that argc is never equal to zero and the array argv always contains at least 1 c string.

Why bother with command line programs?

Command line arguments make programs more flexible. They allow users to run the same program in different ways, often to provide more or less detailed output or otherwise change the behavior at runtime.

C++ is primarily used in systems programming and is a fundamental part of all *nix programs. *nix is short for Unix (and friends), MacOS X, and GNU/Linux. The combination of command line argument handling and taking input from standard input and writing output to standard output is the core around which most *nix programs are designed.

3.3.1. Parsing command line arguments

Parsing the command line is all about getting the user entered C strings from the command line and into our program in a useful form.

The important thing to remember is that argc and argv are passed automatically to main and are available for use. If you run a program named foo invoked as:

/home/dave/foo -n 10 www.sdmesa.edu

Then argc would be set = 4 and array argv would contain 4 arrays of length 15:

The two dimensional array argv

Different program foo invocations would result in different values for argc and argv.

There is nothing special about the character -. It is a convention used to distinguish command line arguments with special meaning (the switches) from other content.

A simple echo program can demonstrate using command line parameters in a program.

repl.it is a website that provides a variety of compilers online. Press the “play” button to compile and run the program.

You can run this program manually in the console or shell by typing

./main

Try This!

Run main with a variety of inputs, such as:

San Diego
"Mesa College"

Can you explain the differences?

Everything that is passed to main through argv is a C string. If you expect to receive a number on the command line, you need to transform the value from a character array into the appropriate numeric value yourself.

Traditional command line argument parsing proceeds as follows:

foreach argument
do
   if the current value equals an expected value
      process the argument
   else if the current value equals a different expected value
      process the argument
   else
      let the user know we received something unexpected
   done if
done foreach

There are many ways to check if two character arrays are equivalent. In this example, we use strcmp:

if (std::strcmp(argv[i], "-h") == 0) {
  // display help text
  break;
}

The strcmp and related functions are defined in the legacy C string header <cstring>. The function compares two null-terminated byte strings lexicographically (the way they would sort alphabetically). The sign of the result is the sign of the difference between the values of the first pair of characters (both interpreted as unsigned char) that differ in the two strings. The behavior is undefined if either argument are not pointers to null-terminated strings.

If the function returns 0, the the two arrays are considered equivalent.

Sometimes a command line argument is used to communicate that a value of a particular type is expected to follow. Let’s say we want our hello world program to repeat its message a certain number of times. We need a way to communicate this information to the program.

if (std::strcmp(argv[i], "-r") == 0) {
  // We should try to repeat,
  // increment the loop counter based on argc
  ++i;
  if (i < argc) {              // is there really a next argument?
      repeat = atoi(argv[i]);
  } else {
    std::cerr << "Error using '-r' argument: no repeat value provided\n";
}

There are many other ways to process the command line and many libraries exist to aid in the task. The technique presented here is simple and only uses facilities from the standard library.

Try This!

Run this program with a variety of inputs and see what happens.

Try passing no arguments or switches, the same switch more than once, and a switch with no value after it.

A common source of confusion is distinguishing between ‘standard input’ and the command line. Parameters passed to a program after the program name are only stored in the array argv. Most operating systems allow you to use the special characters <, > (redirection operators) and | pipe operators to direct data into the standard input of a program. Information sent to a program using redirection or pipes is immediately available for use by any facility that can process the standard input stream, such as cin.

You can also use cin to manage a ‘scripted conversion’ with a user, where you prompt for input using cout and process the input using cin, however, processing standard input using redirection is far more flexible in terms of creating reusable programs that work together.

This idea is the foundation of Unix and its many derivatives, including GNU/Linux and Mac OS.


More to Explore

You have attempted of activities on this page