argc and argv in C: read arguments safely
Understand argc and argv in C, valid indexes, argv[argc] as NULL, and the check to make before reading a command-line argument.
You run ./sum 3 7, then meet argc and argv in main's prototype. The first tells you how many entries arrived. The second gives you their strings, in the order the program received them.
In short
In C, argc is the number of usable pointers in argv. When argc is 3, the valid indexes run from 0 through 2, and argv[3] is NULL. In an ordinary shell launch, argv[0] names the program and the first supplied argument is argv[1], so check argc before reading that index.
What do argc and argv contain for ./program red "two words"?
The shell splits a command before the program starts. Spaces separate arguments unless they are inside quotes, so "two words" arrives as one string. This program prints the structure it receives and walks argv up to its final null pointer.
#include <stdio.h>
int main(int argc, char *argv[]){ int i;
printf("argc=%d\n", argc); i = 0; while (argv[i] != NULL) { printf("argv[%d]=%s\n", i, argv[i]); i++; } printf("argv[%d]=NULL\n", i); return 0;}$ gcc -std=c17 -Wall -Wextra -Werror argv-layout.c -o argv-layout$ ./argv-layout red "two words"argc=3argv[0]=./argv-layoutargv[1]=redargv[2]=two wordsargv[3]=NULL$ ./argv-layoutargc=1argv[0]=./argv-layoutargv[1]=NULLThe three counted pointers are argv[0], argv[1], and argv[2]. argv[3] is not an argument. It is the sentinel required by the language. That makes a loop ending at NULL possible, but argc is clearer when your program requires an exact number of arguments.
- ./sum 3 7the command written in the shell
- argc = 3three pointers before the sentinel
- argv[0..2]./sum, 3, 7
- argv[3] = NULLthe boundary after the last argument
Why does argv[1] sometimes crash?
argv[1] exists as a string only when argc is at least 2. With no user argument, a normal launch gives argc == 1 and argv[1] == NULL. Passing that pointer to printf with %s, strcmp, or strtol does not validate it. Those functions expect a string that exists.
Check the count before any read. This example accepts exactly one word and prints usage otherwise. The fallback to "program" also avoids passing a null pointer to %s on an implementation that invokes main with argc == 0.
#include <stdio.h>
int main(int argc, char *argv[]){ const char *name;
name = argc > 0 ? argv[0] : "program"; if (argc != 2) { fprintf(stderr, "usage: %s WORD\n", name); return 2; } printf("word=%s\n", argv[1]); return 0;}$ gcc -std=c17 -Wall -Wextra -Werror argv-exact.c -o argv-exact$ ./argv-exact helloword=hello$ ./argv-exact; echo status=$?usage: ./argv-exact WORDstatus=2$ ./argv-exact hello extra; echo status=$?usage: ./argv-exact WORDstatus=2printf("%s\n", argv[1]);if (argc != 2) return 2;printf("%s\n", argv[1]);Is argv[0] always the program name?
The standard says that when argc is greater than zero, argv[0] represents the program name. Its form depends on the environment: you may get ./sum, a full path, or an empty string when that name is unavailable. Do not use it to find a file or decide a business option.
On Linux, execve also receives a null-terminated argument vector. The process launcher chooses its first element, which is why the contents of argv[0] are not a reliable identity for the binary.
When should I use argc, and when should I walk argv to NULL?
Use argc for an expected shape, such as argc != 2 for one user argument. Loop from index 1 to argc - 1 when your program accepts a variable number of arguments. A loop testing argv[i] != NULL is valid too, but it naturally includes argv[0] when it starts at zero.
To turn the strings "3" and "7" into numbers, do not add them directly. They are still characters. Parsing an integer command-line argument with strtol shows how to validate the whole conversion.
arg_count
Write a program that prints how many arguments came after the executable name. You have to distinguish argc from the number of user arguments.
Frequently asked questions
Does argc count the program name?
In a normal launch, yes. ./tool blue green gives argc == 3: the program at index 0, then blue and green.
Why does argv have a NULL entry after the last argument?
The C standard requires that sentinel. A function can therefore walk the array without receiving argc, as long as it stops before dereferencing the null pointer.
Can I modify argv?
Yes. In the hosted environment described by the standard, argc, argv, and the strings it points to are modifiable. Avoid doing that while parsing options. Keep the inputs intact, or copy the part you need to transform.
Why can argc be 0?
Hosted C only requires a nonnegative value. Your shell will almost always supply the program too, but argc > 0 is a simple guard when portable code needs to print argv[0].
Sources
