How Optind Variable Gets Assigned in C
-
Use the
getopt
Function to Parse Command-Line Options in C -
Use
optind
andoptarg
Variables to Processargv
Elements in C -
Use the
getopt_long
Function to Parse Command-Line Options in C - Conclusion
In C programming, the optind
variable is often used in conjunction with command-line argument parsing libraries like getopt
or getopt_long
. It keeps track of the index of the next argument to be processed.
optind
can be assigned in several ways depending on the method used for parsing command-line arguments. This article will demonstrate multiple methods about how the optind
variable gets assigned in C.
Use the getopt
Function to Parse Command-Line Options in C
Typical command-line programs on UNIX-based systems take arguments and options. Options are usually specified with characters that follow hyphens, and each unique character either indicates information about the given argument or yields the specific behavior of the program to be executed.
Options can have mandatory or optional arguments; in the latter case, it’s common for programs to allow grouping of the options after a single hyphen, and the only argument may be passed at the end of the command.
The getopt
function is used to parse the options, retrieve given arguments from the program, and execute the corresponding code paths based on the input. getopt
takes three arguments, the first two of which are argc
and argv
passed to the main
function.
The third argument is optstring
- a pointer to a character string representing the legitimate option characters. getopt
needs to be called successively until every option is retrieved.
Syntax:
#include <unistd.h>
int getopt(int argc, char *const argv[], const char *optstring);
argc
: Number of arguments passed to the program.argv
: Array of strings containing the arguments.optstring
: String containing the expected options. Each character represents a single-letter option. If a character inoptstring
is followed by a colon (:
), it indicates that the option requires an argument.
The function returns:
-1
when there are no more options to process.- The character code of the next option found in the command line.
- If an option requires an argument,
optarg
(externally defined) will contain a pointer to the option’s argument.
Additionally, the external variable optind
is used to track the index of the next argument to be processed; that is not an option.
In the following example, we demonstrate a program that takes options with p
and x
characters. Note that optstring
starts with the colon, which indicates the value that needs to be returned by the getopt
call when the missing arguments are encountered.
Also, a colon specified after a character (e.g., p
) indicates that the argument is required for the option; two colons mean the argument is optional. The same option character can be passed multiple times on the command line.
The getopt
function returns the option character if successful or returns the character ?
if the encountered option character is not in optstring
.
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int opt, xnum = 0;
char *pstr = NULL;
while ((opt = getopt(argc, argv, ":p:x")) != -1) {
printf("opt = %3d (%c); optind = %d\n", opt, opt, optind);
switch (opt) {
case 'p':
pstr = optarg;
break;
case 'x':
xnum++;
break;
case ':':
fprintf(stderr,
"Missing argument!\n"
"Usage: %s [-p arg] [-x]\n",
argv[0]);
exit(EXIT_FAILURE);
case '?':
fprintf(stderr,
"Unrecognized option!\n"
"Usage: %s [-p arg] [-x]\n",
argv[0]);
exit(EXIT_FAILURE);
default:
fprintf(stderr, "Unexpected case in switch()");
exit(EXIT_FAILURE);
}
}
exit(EXIT_SUCCESS);
}
Sample Command:
./program_name -p hello -p there
Output:
opt = 112 (p); optind = 3
opt = 112 (p); optind = 5
Use optind
and optarg
Variables to Process argv
Elements in C
The previous code sample demonstrates the typical getopt
usage, where the function is called from a while
loop expression until it returns the error code -1
. Meanwhile, the switch
statement checks for possible getopt
return values to execute the corresponding code blocks.
Note that the optind
variable represents the next element’s index in the argv
, and it’s initialized to 1
before the first call to getopt
.
On the other hand, optarg
is an external variable that points to the argument following the current option character. If the option does not include an argument, then optarg
is set to zero.
optind
: It is an external variable that tracks the index of the nextargv
element to be processed. Initially set to 1,optind
is updated bygetopt
as options are parsed.optarg
: Also an external variable, it holds the argument (if any) associated with the current option.optarg
is set bygetopt
when an option that expects an argument is encountered.
The primary use of optind
and optarg
revolves around parsing command-line options. This involves iterating through the command-line arguments using getopt
in a loop until all options are processed.
The next code example shows how to save the argument pointed by the optarg
variable and then operate on it as needed. Mind that the argument can follow the option without a space delimiter.
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int opt, xnum = 0;
char *pstr = NULL;
while ((opt = getopt(argc, argv, ":p:x")) != -1) {
printf("opt = %3d (%c); optind = %d\n", opt, opt, optind);
switch (opt) {
case 'p':
pstr = optarg;
break;
case 'x':
xnum++;
break;
case ':':
fprintf(stderr,
"Missing argument!\n"
"Usage: %s [-p arg] [-x]\n",
argv[0]);
exit(EXIT_FAILURE);
case '?':
fprintf(stderr,
"Unrecognized option!\n"
"Usage: %s [-p arg] [-x]\n",
argv[0]);
exit(EXIT_FAILURE);
default:
fprintf(stderr, "Unexpected case in switch()");
exit(EXIT_FAILURE);
}
}
if (xnum != 0) printf("-x was specified (count=%d)\n", xnum);
if (pstr != NULL) printf("-p was specified with the value \"%s\"\n", pstr);
if (optind < argc)
printf("First non-option argument is \"%s\" at argv[%d]\n", argv[optind],
optind);
exit(EXIT_SUCCESS);
}
This code exemplifies a robust approach to parsing command-line options in C, utilizing getopt
alongside optind
and optarg
to efficiently process arguments, handle options, and provide informative output regarding the specified options and their arguments.
Sample Command:
./program_name -p hello
Output:
opt = 112 (p); optind = 3
-p was specified with the value "hello"
Use the getopt_long
Function to Parse Command-Line Options in C
The getopt_long
function is part of the C standard library <getopt.h>
. It facilitates the parsing of command-line options, allowing programs to handle both short and long options, providing a more descriptive and user-friendly interface.
Syntax:
#include <getopt.h>
int getopt_long(int argc, char *const argv[], const char *optstring,
const struct option *longopts, int *longindex);
argc
: Number of arguments passed to the program.argv
: Array of strings containing the arguments.optstring
: String containing the short options.longopts
: Array ofstruct option
defining long options.longindex
: Pointer to an integer to store the index of the next long option found (can beNULL
).
Using struct option
The struct option
structure allows defining long-named options alongside their attributes:
struct option {
const char *name;
int has_arg; // Indicates if the option requires an argument
int *flag; // If not NULL, points to a variable to set a value for the option
int val; // Value to return if the option is found
};
name
: The long name of the option.has_arg
: Specifies whether the option requires an argument (values:no_argument
,required_argument
, oroptional_argument
).flag
: If notNULL
, it sets a variable to a specified value when the option is found.val
: The value to return if the option is encountered.
Let’s delve into an example showcasing the usage of getopt_long
to process command-line options:
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
struct option long_options[] = {{"help", no_argument, NULL, 'h'},
{"verbose", no_argument, NULL, 'v'},
{"output", required_argument, NULL, 'o'},
{0, 0, 0, 0}};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, "hvo:", long_options, &option_index)) !=
-1) {
switch (opt) {
case 'h':
// Process --help or -h option
break;
case 'v':
// Process --verbose or -v option
break;
case 'o':
// Process --output or -o option with argument
printf("Option 'output' specified with value: %s\n", optarg);
break;
case '?':
// Invalid option or missing argument
fprintf(stderr, "Unrecognized option\n");
exit(EXIT_FAILURE);
}
}
// Process non-option arguments if any
for (; optind < argc; optind++) {
printf("Non-option argument: %s\n", argv[optind]);
}
return 0;
}
The output of the code depends on the arguments passed when executing the program. Let’s break down the code’s behavior:
-
It defines three long options:
--help
(-h
),--verbose
(-v
), and--output
(-o
) with an expected argument. -
Inside the
while
loop, it usesgetopt_long
to process command-line options until no options are left (opt
becomes-1
). -
For each recognized option, the corresponding
case
block is executed:'h'
: Represents the help option.'v'
: Represents the verbose option.'o'
: Represents the output option, and it prints the provided argument usingoptarg
.'?'
: Indicates an unrecognized option or a missing argument, triggering an error message and program termination with failure status.
After parsing options, the code iterates through any remaining non-option arguments using optind
and prints them.
To simulate the output, consider executing the program with different arguments:
./program_name -o output_value --verbose argument1 argument2
The output would display:
Option 'output' specified with value: output_value
Non-option argument: argument1
Non-option argument: argument2
This output illustrates the processing of the --output
(-o
) option with the provided value, followed by the printing of non-option arguments (argument1
and argument2
) encountered after parsing options.
Sample Command:
./program_name -o hello
Output:
Option 'output' specified with value: hello
Key Points:
- Structuring Long Options:
struct option
is used to define long-named options with their respective attributes. - Looping Through Options: The
while
loop utilizesgetopt_long
to parse command-line options, including both short and long options. - Switch Statement Handling Options: The
switch
statement processes each recognized option according to its corresponding case. - Error Handling: It handles cases of unrecognized options or missing arguments.
- Accessing Non-Option Arguments:
optind
is used to access non-option arguments after option parsing.
Conclusion
In summary, understanding the intricacies of command-line argument parsing in C involves using variables like optind
in conjunction with libraries such as getopt
or getopt_long
. These variables aid in tracking the index of the next argument to be processed in command-line argument parsing.
The getopt
function is commonly used to handle short options in C programs. It processes options characterized by single letters, allowing for arguments to be passed alongside specific options.
Utilizing optind
and optarg
variables with getopt
helps navigate through command-line arguments efficiently, indicating the next argument to be processed and pointing to the argument associated with the current option.
Additionally, getopt_long
offers a more versatile approach by supporting both short and long options, enhancing readability and user-friendliness. Using a struct option
, it defines long-named options alongside their attributes and allows comprehensive parsing of command-line options, enabling error handling and accessing non-option arguments with ease.
Both getopt
and getopt_long
facilitate the efficient handling of command-line interfaces in C, allowing developers to create robust and user-friendly programs by providing mechanisms to parse options, process arguments, and manage non-option elements effectively. These tools, in combination with optind
and optarg
, empower programmers to develop flexible and feature-rich command-line applications in C.
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn Facebook