C语言 main() 函数参数详解
- C语言进阶
- 2026-05-24
- 9热度
- 0评论
1. 核心理解
int main(int argc, char **argv)
1.1 char **argv 双重指针
argv 是双重指针,指向一个 char 类型的数组,每个 char 再指向一个字符串。
argv ─→ argv[0] ─→ "D:\Portable\RedPanda-CPP\main.exe"
─→ argv[1] ─→ "hello"
─→ argv[2] ─→ "world"
─→ argv[3] ─→ NULL
关键:argv[argc] == NULL,数组以 NULL 结束。
// 当 argc = 3 时
argv[0] = "D:\Portable\RedPanda-CPP\main.exe";
argv[1] = "hello";
argv[2] = "world";
argv[3] = NULL; // 数组结束标记
2. 基础示例
#include <stdio.h>
int main(int argc, char **argv) {
for (int i = 0; i < argc; i++) {
// &argv[i] argv数组中第 i 个元素的地址
// argv[i] 第 i 个参数字符串的首地址
printf("argv[%d] address=%p *addr=%p value=%s\r\n",
i, &argv[i], argv[i], argv[i]);
}
return 0;
}
等价写法
int main(int argc, char **argv) // 推荐(强调指针)
int main(int argc, char *argv[]) // 等价(强调数组)
运行示例
gcc main.c -o main.exe
D:\Portable\RedPanda-CPP\main.exe hello world
输出:
argv[0] address=0000002286705bf0 *addr=0000002286705c40 value=D:\Portable\RedPanda-CPP\main.exe
argv[1] address=0000002286705bf8 *addr=0000002286705d00 value=hello
argv[2] address=0000002286705c00 *addr=0000002286705d40 value=world

运行截图
3. 内存布局
完整结构
argc = 3
栈上的 argv 数组 堆/数据段上的字符串
┌─────────────┐
│ argv[0] │ ─────→ "D:\Portable\RedPanda-CPP\main.exe"
│ 0x2286705c40│
├─────────────┤
│ argv[1] │ ─────→ "hello"
│ 0x2286705d00│
├─────────────┤
│ argv[2] │ ─────→ "world"
│ 0x2286705d40│
├─────────────┤
│ argv[3] │ ─────→ NULL
└─────────────┘
地址间隔:8 字节(64位指针)
&argv[0] = 0x2286705bf0
&argv[1] = 0x2286705bf8
&argv[2] = 0x2286705c00
三层地址关系
以 argv[1] = "hello" 为例:
&argv[1] // char ** → argv数组中第1个指针的地址 (0x2286705bf8)
argv[1] // char * → 字符串首地址 (0x2286705d00)
*argv[1] // char → 第一个字符 ('h')
argv[1][0] // 'h'
argv[1][1] // 'e'
argv[1][5] // '\0'
4. 参数说明
| 参数 | 含义 |
|---|---|
| argc | 参数个数(≥1) |
| argv[0] | 程序名称(路径) |
argv[1] ~ argv[argc-1] |
用户传入的参数 |
argv[argc] |
NULL(数组结束标记) |
5. 实用示例
参数校验
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
if (argc != 3) {
printf("用法: %s <数字1> <数字2>\n", argv[0]);
return 1;
}
int a = atoi(argv[1]);
int b = atoi(argv[2]);
printf("%d + %d = %d\n", a, b, a + b);
return 0;
}
解析命令行选项
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
int verbose = 0;
char *input_file = NULL;
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-v") == 0) {
verbose = 1;
} else if (strcmp(argv[i], "-f") == 0 && i + 1 < argc) {
input_file = argv[i + 1];
i++;
}
}
if (verbose) printf("详细模式已开启\n");
if (input_file) printf("输入文件: %s\n", input_file);
return 0;
}
6. 常见错误
数组越界
❌ 错误:直接访问 argv[1] 而不检查 argc,无参数时会崩溃。
// ❌ 错误
int main(int argc, char **argv) {
printf("%s\n", argv[1]); // 崩溃
return 0;
}
// ✅ 正确
int main(int argc, char **argv) {
if (argc < 2) {
printf("需要至少 1 个参数\n");
return 1;
}
printf("%s\n", argv[1]);
return 0;
}
类型转换
argv 都是字符串,需要手动转换:
int num = atoi(argv[1]); // 字符串 → 整数
float f = atof(argv[1]); // 字符串 → 浮点数
long l = strtol(argv[1], NULL, 10); // 更安全的转换
字符串修改
⚠️ 警告:argv 指向的字符串通常是只读的,直接修改可能崩溃。需要修改时先复制到缓冲区。
// ⚠️ 危险
argv[1][0] = 'X';
// ✅ 安全
char buffer[256];
strncpy(buffer, argv[1], sizeof(buffer) - 1);
buffer[0] = 'X';
7. 快速参考
| 表达式 | 类型 | 含义 |
|---|---|---|
argc |
int |
参数个数(≥1) |
argv |
char ** |
指向字符串数组的指针 |
argv[i] |
char * |
第 i 个字符串的首地址 |
argv[i][j] |
char |
第 i 个字符串的第 j 个字符 |
&argv[i] |
char ** |
argv 数组第 i 个元素的地址 |
argv[argc] |
char * |
NULL(数组结束标记) |