Adam Richardson's Site

C Program Argument Notes

Table of Contents

<2022-05-01 Sun>

Receiving arguments

  • The main should receive argc (argument count) and argv (argument variables).
  • The first argument (index 0) is usually the command run by the user to invoke the program
  • You should not assume that argc > 0

Example

#include <stdio.h>

int main(int argc, char **argv) {
  int i;
  printf("argc: %d\n", argc);
  for (i = 0; i < argc; i++) {
    printf("argv[%d]: %s\n", i, argv[i]);
  }
  return 0;
}
#!/bin/sh

# Exit on command failure
set -e

../../config/tangle.sh c_program_arguments.org

cd ~/tmp
gcc -o arg_example arg_example.c
./arg_example hello world

Parsing arguments with getopt

  • Link to the GNU libc manual page on getopt
  • The getopt function is in unistd.h
  • The getopt_long function is in getopt.h
  • Normal options are preceded by -
  • Long options are preceded by -- instead of -
  • Long options are specified in the struct options
  • This struct allows for options to potentially have an argument or not
  • The list of options needs to be terminated with one element containing all zeroes

Example

#include <stdio.h>
#include <getopt.h>

int main(int argc, char **argv) {
  int c;
  int option_index = 0;

  static struct option long_options[] = {
    {"hello", no_argument, 0, 'h'},
    {"world", no_argument, 0, 'w'},
    {0, 0, 0, 0}
  };

  while (1) {
    c = getopt_long(argc, argv, "hw", long_options, &option_index);
    if (c == -1) {
      break;
    }

    switch(c) {
    case 'h':
      printf("hello ");
      break;
    case 'w':
      printf("world ");
      break;
    }
  }

  return 0;
}
#!/bin/sh

# Exit on command failure
set -e

../../config/tangle.sh c_program_arguments.org

cd ~/tmp
gcc -o arg_getopt_example arg_getopt_example.c
./arg_getopt_example -w -h --hello --world

When argc===0

  • LWN: Handling argc==0 in the kernel
  • It is only a convention that argv[0] is the binary name being executed
  • Technically whoever calls execve to launch the program controls what argv[0] is
  • There is a third pointer for the environment that is immediately after argv
  • The full main prototype looks like this, int main(int argc, char *argv[], char *envp[])
  • The environment, envp starts immediately after argv
  • if execve called the program with argv as null, so argv[1] will actually be envp[0]
  • Technically the POSIX standard allows for an empty argv
  • The OpenBSD manpage for execve requires that at least one non null argument be present in argv