Site Tools


wiki:getopt.h

Table of Contents

getopt.h

Parsing argv by hand gets old fast once you have more than two flags. getopt.h is a POSIX/GNU header that provides getopt for short options (-v, -o file) and getopt_long for long options (--verbose, --output=file). It handles the argument loop, the option string, and the optarg/optind bookkeeping.

#include <getopt.h>
#include <stdio.h>
 
int main(int argc, char *argv[]) {
    int verbose = 0;
    const char *outfile = NULL;
    int c;
 
    while ((c = getopt(argc, argv, "vo:")) != -1) {
        switch (c) {
        case 'v': verbose = 1;       break;
        case 'o': outfile = optarg;  break;  // optarg points to the argument
        case '?': return 1;                  // unknown option, getopt printed an error
        }
    }
    // non-option arguments start at argv[optind]
    for (int i = optind; i < argc; i++)
        printf("input: %s\n", argv[i]);
 
    return 0;
}

The option string "vo:" means: -v takes no argument; -o requires one (the colon). A leading colon in the string (":vo:") suppresses getopt's automatic error message and returns ':' for a missing argument instead, letting you handle errors yourself.

getopt_long adds long option support via a struct option array:

static struct option long_opts[] = {
    {"verbose", no_argument,       NULL, 'v'},
    {"output",  required_argument, NULL, 'o'},
    {"help",    no_argument,       NULL, 'h'},
    {0, 0, 0, 0}                             // sentinel
};
 
while ((c = getopt_long(argc, argv, "vo:h", long_opts, NULL)) != -1) { ... }

The third field in struct option can point to a flag variable to set instead of returning a character — useful for boolean flags you want to set directly. Long options with optional_argument require --opt=value syntax; --opt value is not recognised as providing an argument.

getopt permutes argv as it processes it, moving non-option arguments to the end (GNU behaviour). Setting POSIXLY_CORRECT in the environment, or using a leading + in the option string, stops processing at the first non-option argument instead.

Practice

// compile: gcc -o tool tool.c
// run: ./tool -v --output=out.txt file1.txt file2.txt
// description: parse a mix of short and long options
 
#include <getopt.h>
#include <stdio.h>
 
int main(int argc, char *argv[]) {
    int verbose = 0;
    const char *outfile = "a.out";
    int c;
 
    static struct option opts[] = {
        {"verbose", no_argument,       NULL, 'v'},
        {"output",  required_argument, NULL, 'o'},
        {0, 0, 0, 0}
    };
 
    while ((c = getopt_long(argc, argv, "vo:", opts, NULL)) != -1) {
        switch (c) {
        case 'v': verbose = 1;        break;
        case 'o': outfile = optarg;   break;
        case '?': return 1;
        }
    }
 
    printf("verbose=%d  output=%s\n", verbose, outfile);
    for (int i = optind; i < argc; i++)
        printf("  input: %s\n", argv[i]);
 
    return 0;
}

Try ./tool --output out.txt file.txt (space-separated) — it works. Then try ./tool --output=out.txt file.txt (equals sign) — it also works. Now try optional_argument for a flag and compare: --opt value will not bind value as the argument, only --opt=value will.

wiki/getopt.h.md · Last modified: by 127.0.0.1