Master Linux Command-Line Arguments: argc, argv, getopt, and getopt_long Explained
This guide explains how Linux programs receive command‑line arguments using argc and argv, demonstrates parsing techniques with manual loops, getopt, getopt_long, and getopt_long_only, and provides complete C code examples with expected outputs and common pitfalls.
argc and argv
When a Linux program starts, the main function receives int argc (the number of command‑line arguments) and char *argv[] (an array of strings, each representing one argument). argv[0] is the program name; the remaining elements hold the user‑supplied parameters.
int main(int argc, char *argv[])
{
// argc: count of command‑line arguments
// argv: array of argument strings, terminated by a NULL pointer
}Example that prints the count and each argument:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("argc=%d
", argc);
for (int i = 0; i < argc; i++) {
printf("argv[%d]: %s
", i, argv[i]);
}
return 0;
}Running ./prog arg1 arg2 arg3 yields:
argc=4
argv[0]: ./prog
argv[1]: arg1
argv[2]: arg2
argv[3]: arg3Manual option parsing
A simple loop can skip argv[0] and examine each argument. If an argument starts with -, a switch statement handles known options:
int c;
while (--argc > 0 && (*++argv)[0] == '-') {
while ((c = *++argv[0])) {
switch (c) {
case 'a': /* handle -a */ break;
case 'b': /* handle -b */ break;
default: fprintf(stderr, "illegal option %c
", c);
}
}
}Using getopt
The GNU library provides getopt to simplify short‑option parsing. Its prototype is:
#include <unistd.h>
int getopt(int argc, char * const argv[], const char *optstring); optstringdefines which options are accepted and whether they require an argument ( : for required, :: for optional). Example:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int opt;
const char *optstring = "ab:c::"; // a: no arg, b: requires arg, c: optional arg
while ((opt = getopt(argc, argv, optstring)) != -1) {
switch (opt) {
case 'a': printf("-a detected
"); break;
case 'b': printf("-b arg = %s
", optarg); break;
case 'c': printf("-c arg = %s
", optarg ? optarg : "(none)"); break;
case '?': fprintf(stderr, "unknown option
"); break;
}
}
return 0;
}Parsing long options with getopt_long
getopt_longextends getopt to support GNU‑style long options (e.g., --help). Its signature is:
#include <getopt.h>
int getopt_long(int argc, char * const argv[], const char *optstring,
const struct option *longopts, int *longindex);The struct option describes each long option:
struct option {
const char *name; // option name without leading '--'
int has_arg; // no_argument, required_argument, optional_argument
int *flag; // if non‑NULL, set *flag to val and return 0
int val; // value to return or store in *flag
};Example definition and usage:
#include <stdio.h>
#include <getopt.h>
int main(int argc, char *argv[])
{
static struct option long_opts[] = {
{"reqarg", required_argument, NULL, 'r'},
{"optarg", optional_argument, NULL, 'o'},
{"noarg", no_argument, NULL, 'n'},
{NULL, 0, NULL, 0}
};
int opt, option_index = 0;
while ((opt = getopt_long(argc, argv, "a::b:c:d", long_opts, &option_index)) != -1) {
printf("opt = %c optarg = %s optind = %d argv[optind] = %s option_index = %d
",
opt, optarg, optind, argv[optind], option_index);
}
return 0;
}getopt_long_only
getopt_long_onlybehaves like getopt_long but also treats a single dash followed by a word (e.g., -help) as a long option when it matches an entry in longopts. This allows mixed short/long styles.
Comprehensive example
The program below demonstrates a robust argument parser that supports short and long options, prints a usage message, and handles errors gracefully.
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <getopt.h>
#include <sys/param.h>
#define ETHCHECKD_VERSION "1.1"
int delay_up = 0;
char *interface = "eth0";
void usage(char *p) {
if (strrchr(p, '/'))
p = strchr(p, '/') + 1;
printf("%s [options]
"
" -i --iface=IFACE Specify ethernet interface (%s)
"
" -d --delay-up=SECS Specify delay time (%d)
"
" -h --help Show this help
"
" -v --version Show version
",
p, interface, delay_up);
}
void parse_args(int argc, char *argv[]) {
static struct option long_options[] = {
{"iface", required_argument, 0, 'i'},
{"delay-up", required_argument, 0, 'd'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'v'},
{0, 0, 0, 0}
};
int opt, option_index = 0;
while ((opt = getopt_long(argc, argv, "i:d:hv", long_options, &option_index)) != -1) {
switch (opt) {
case 'i':
interface = strdup(optarg);
printf("interface %s
", interface);
break;
case 'd':
delay_up = atoi(optarg);
printf("delay_up %d
", delay_up);
break;
case 'h':
usage(argv[0]);
break;
case 'v':
printf("peng %s
", ETHCHECKD_VERSION);
break;
default:
fprintf(stderr, "Unknown parameter.
");
exit(1);
}
}
}
int main(int argc, char *argv[]) {
parse_args(argc, argv);
return 0;
}Typical invocations
Short options: ./param -i eth3 -d 15 prints the selected interface and delay.
Long options: ./param --iface eth3 --delay-up 15 produces the same result.
Help: ./param -h or ./param --help displays the usage message.
Version: ./param -v or ./param --version shows the program version.
This example shows how to combine getopt_long with a custom usage function, handle missing arguments, and report unknown options, providing a solid template for building robust command‑line tools in C.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
