The C entry point may receive argc and argv, where argc counts argument strings and argv[0] conventionally identifies the program invocation. Validate the count before indexing and treat every argument as untrusted text requiring range and format checks.
Command line arguments allow you to pass input to a C program when you run it from the terminal. Instead of hardcoding values, the user can provide them at runtime:
./myprogram hello 42 3.14 C receives these arguments through two special parameters of main():
| Index | Value | Description |
|---|---|---|
| argv[0] | "./myprogram" | Program name (always present) |
| argv[1] | "hello" | First user argument |
| argv[2] | "42" | Second user argument (string!) |
| argv[argc] | NULL | Always NULL - marks end of array |
./myprogram hello 42 3.14
#include <stdio.h>
int main(int argc, char *argv[]) {
printf("Program name: %s\n", argv[0]);
printf("Argument count: %d\n", argc);
printf("\nAll arguments:\n");
for (int i = 0; i < argc; i++) {
printf(" argv[%d] = \"%s\"\n", i, argv[i]);
}
return 0;
}
/*
Run: ./args hello world 123
Output:
Program name: ./args
Argument count: 4
All arguments:
argv[0] = "./args"
argv[1] = "hello"
argv[2] = "world"
argv[3] = "123"
*/
Since all arguments are strings, use the standard library functions to convert them:
| Function | Header | Converts to | Example |
|---|---|---|---|
| atoi(str) | stdlib.h | int | atoi("42") -> 42 |
| atof(str) | stdlib.h | double | atof("3.14") -> 3.14 |
| atol(str) | stdlib.h | long | atol("100000") -> 100000 |
| strtol(str, &end, base) | stdlib.h | long | Safer, detects errors |
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
// Usage: ./calc 10 + 5
if (argc != 4) {
printf("Usage: %s <num1> <op> <num2>\n", argv[0]);
printf("Example: ./calc 10 + 5\n");
return 1;
}
double a = atof(argv[1]);
char op = argv[2][0];
double b = atof(argv[3]);
double result;
switch (op) {
case '+': result = a + b; break;
case '-': result = a - b; break;
case '*': result = a * b; break;
case '/':
if (b == 0) { printf("Error: division by zero\n"); return 1; }
result = a / b;
break;
default:
printf("Unknown operator: %c\n", op);
return 1;
}
printf("%.2f %c %.2f = %.2f\n", a, op, b, result);
return 0;
}
/*
Run: ./calc 10 + 5 -> 10.00 + 5.00 = 15.00
Run: ./calc 7 / 2 -> 7.00 / 2.00 = 3.50
Run: ./calc 3 * 4 -> 3.00 * 4.00 = 12.00
*/
Always validate argc before accessing argv elements. Accessing argv[1] when argc == 1 is undefined behaviour.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "Error: no arguments provided\n");
fprintf(stderr, "Usage: %s <number>\n", argv[0]);
return EXIT_FAILURE;
}
// Use strtol for safe integer conversion (detects errors)
char *endptr;
errno = 0;
long num = strtol(argv[1], &endptr, 10);
if (errno != 0 || *endptr != '\0') {
fprintf(stderr, "Error: '%s' is not a valid integer\n", argv[1]);
return EXIT_FAILURE;
}
printf("You entered: %ld\n", num);
printf("Squared: %ld\n", num * num);
return EXIT_SUCCESS;
}
/*
Run: ./validate 7 -> You entered: 7 / Squared: 49
Run: ./validate abc -> Error: 'abc' is not a valid integer
Run: ./validate -> Error: no arguments provided
*/
For numeric input, use strtol or a related function with errno reset, an end pointer, and explicit range validation. atoi cannot distinguish invalid text from a valid zero and cannot report overflow. Reject trailing characters unless the command syntax intentionally permits them.
Document options, required operands, defaults, and exit statuses in one usage function. Never modify argument strings unless the implementation contract explicitly allows the intended operation; copy values that need normalization or long-term ownership.
Explore 500+ free tutorials across 20+ languages and frameworks.