两种获取命令行参数的方法
在 C 语言中,主要有两种方式来获取命令行传入的参数:

(图片来源网络,侵删)
- 使用
main函数的参数 (最常用、最标准) - 使用 Windows API 函数 (
GetCommandLine和CommandLineToArgvW)
使用 main 函数的参数 (推荐)
这是 C 语言标准规定的方法,也是跨平台(Linux, macOS 等)通用的方法。
1 函数原型
main 函数可以带两个参数:
int main(int argc, char *argv[]);
或者更严谨的写法(使用 const 修饰,表示 argv 指向的内容不会被修改):
int main(int argc, const char *argv[]);
2 参数详解
-
argc(argument count - 参数计数)
(图片来源网络,侵删)- 类型:
int(整数) - 含义: 表示在命令行中输入的总参数的个数。
- 重要:
argc的值至少为 1,因为即使你没有传入任何参数,程序名称本身也会被算作第一个参数。
- 类型:
-
argv(argument vector - 参数向量)- 类型:
char *[](字符指针数组),或者char **(指向字符指针的指针)。 - 含义: 它是一个字符串数组,存放了所有的命令行参数。
- 重要:
argv[0]永远是程序的名称。 argv[1]到argv[argc - 1]才是你实际传入的参数。
- 类型:
3 示例代码
让我们创建一个名为 cmd_args_demo.c 的文件。
#include <stdio.h>
int main(int argc, const char *argv[]) {
// 打印参数的总个数
printf("参数的总个数 (argc): %d\n", argc);
// 使用一个循环来打印所有参数
printf("\n所有参数列表:\n");
for (int i = 0; i < argc; i++) {
printf("argv[%d] = \"%s\"\n", i, argv[i]);
}
// 根据参数数量执行不同操作
if (argc < 2) {
printf("\n用法: %s <选项> <文件名>\n", argv[0]);
printf("示例: %s --copy file.txt\n", argv[0]);
return 1; // 返回非零值表示程序异常结束
}
// 检查第一个参数是否是 "--copy"
if (strcmp(argv[1], "--copy") == 0) {
if (argc == 3) {
printf("\n正在复制文件: %s\n", argv[2]);
// ... 这里可以添加实际的文件复制代码
} else {
printf("\n错误: --copy 选项需要一个文件名作为参数,\n");
return 1;
}
} else {
printf("\n未知选项: %s\n", argv[1]);
return 1;
}
return 0; // 返回 0 表示程序成功结束
}
4 如何编译和运行
-
保存代码: 将上面的代码保存为
cmd_args_demo.c。 -
打开命令提示符 (CMD) 或 PowerShell:
(图片来源网络,侵删)- 按
Win + R,输入cmd或powershell,然后回车。
- 按
-
编译代码:
- 如果你安装了 MinGW (GCC for Windows),可以使用以下命令:
gcc cmd_args_demo.c -o cmd_args_demo.exe
- 如果你使用 Visual Studio 的开发者命令提示符,可以使用
cl.exe:cl cmd_args_demo.c
- 如果你安装了 MinGW (GCC for Windows),可以使用以下命令:
-
运行程序:
-
不带参数运行:
.\cmd_args_demo.exe
输出:
参数的总个数 (argc): 1 所有参数列表: argv[0] = "cmd_args_demo.exe" 用法: cmd_args_demo.exe <选项> <文件名> 示例: cmd_args_demo.exe --copy file.txt -
带参数运行:
.\cmd_args_demo.exe --copy my_document.txt
输出:
参数的总个数 (argc): 3 所有参数列表: argv[0] = "cmd_args_demo.exe" argv[1] = "--copy" argv[2] = "my_document.txt" 正在复制文件: my_document.txt -
带错误参数运行:
.\cmd_args_demo.exe --delete
输出:
参数的总个数 (argc): 2 所有参数列表: argv[0] = "cmd_args_demo.exe" argv[1] = "--delete" 未知选项: --delete
-
使用 Windows API 函数
这种方法更底层,通常在需要更精细地控制命令行解析时使用,或者在 Windows 特有的程序(如窗口程序)中,因为它们的 main 函数可能没有参数。
1 主要函数
-
GetCommandLineW:- 功能: 获取整个命令行字符串作为一个单一的宽字符字符串。
- 原型:
LPWSTR GetCommandLineW(void); - 注意: 函数名以
W表示它返回的是 Unicode (宽字符) 字符串,这在现代 Windows 编程中是标准做法,如果你需要 ANSI 字符串,可以使用GetCommandLineA,但不推荐。
-
CommandLineToArgvW:- 功能: 将
GetCommandLineW获取的长字符串,解析成一个argc/argv风格的数组。 - 原型:
LPWSTR* CommandLineToArgvW(LPCWSTR lpCmdLine, int* pNumArgs); - 参数:
lpCmdLine: 由GetCommandLineW返回的完整命令行字符串。pNumArgs: 一个指向整数的指针,函数会将解析出的参数个数写入这个整数。
- 返回值: 返回一个
LPWSTR*(宽字符指针数组),也就是argv。必须手动调用LocalFree来释放这个返回的数组,否则会造成内存泄漏。
- 功能: 将
2 示例代码
#include <windows.h>
#include <stdio.h>
#include <tchar.h> // 为了方便使用 TCHAR 宏,处理 Unicode/ANSI
int main() {
// 1. 获取完整的命令行字符串
LPWSTR cmdLine = GetCommandLineW();
// 2. 解析命令行字符串
int argc;
LPWSTR* argv = CommandLineToArgvW(cmdLine, &argc);
// 3. 检查解析是否成功
if (argv == NULL) {
// 解析失败,通常是因为内存不足
printf("CommandLineToArgvW failed. Error code: %d\n", GetLastError());
return 1;
}
// 4. 打印参数
wprintf(L"参数的总个数 (argc): %d\n", argc);
wprintf(L"\n所有参数列表:\n");
for (int i = 0; i < argc; i++) {
wprintf(L"argv[%d] = \"%s\"\n", i, argv[i]);
}
// 5. 使用完毕后,必须释放内存!
LocalFree(argv);
return 0;
}
3 如何编译和运行
编译和运行方式与第一种方法完全相同。
# 编译 (使用 MinGW) gcc api_args_demo.c -o api_args_demo.exe -luser32 # 运行 .\api_args_demo.exe "first arg" /option
输出:
参数的总个数 (argc): 3
所有参数列表:
argv[0] = "api_args_demo.exe"
argv[1] = "first arg"
argv[2] = "/option"
重要注意事项
-
路径中的空格:
- 命令行会将空格作为参数分隔符。
- 如果你的参数(比如一个文件路径)本身包含空格,必须用双引号 括起来。
-
.\my_program.exe "C:\Program Files\My App\config.ini" - 在
main的argv中,这会被正确地解析为一个参数argv[1] = "C:\Program Files\My App\config.ini"。
-
*
main函数的 `char argv[]` 与 Unicode**:- 标准 C 的
main(int argc, char *argv[])使用的是char(单字节/多字节字符)。 - Windows 内部广泛使用 Unicode (UTF-16),当你从命令行复制粘贴一个包含非 ASCII 字符(如中文、日文)的路径时,
argv中的内容可能会出现乱码。 - 解决方案:
- 简单场景: 如果程序只处理 ASCII 字符,
main的参数足够了。 - 专业场景: 为了正确处理所有字符,建议使用
GetCommandLineW和CommandLineToArgvW,这样你的整个程序都可以基于 Unicode 开发,避免乱码问题,在 Visual Studio 中,新项目默认使用 Unicode。
- 简单场景: 如果程序只处理 ASCII 字符,
- 标准 C 的
-
内存管理:
main函数的argv数组及其内容是由 C 运行时库管理的,你不需要手动释放它。- 而
CommandLineToArgvW返回的数组必须调用LocalFree来释放,否则会导致内存泄漏。
| 特性 | main(int argc, char *argv[]) |
GetCommandLineW + CommandLineToArgvW |
|---|---|---|
| 标准性 | C 语言标准,跨平台 | Windows API,仅限 Windows |
| 易用性 | 非常简单,直接使用 | 稍微复杂,需要手动管理内存 (LocalFree) |
| 字符编码 | 通常是 ANSI/MBCS,可能乱码 | Unicode (UTF-16),能正确处理所有字符 |
| 适用场景 | 大多数控制台程序,尤其是需要跨平台的 | Windows 特定程序,需要处理复杂或 Unicode 命令行的场景 |
对于绝大多数 Windows C 控制台台程序,使用 main 函数的参数是首选,它简单、标准且足够用,只有当你遇到编码问题或需要更底层的控制时,才应该考虑使用 Windows API 的方法。
