作者简介
Nebula嵌入式 | 嵌入式软件工程师
🏆技术背景:
22届普通二本院校毕业生
专注于嵌入式软件开发(MCU/RTOS/Linux应用/Linux驱动开发 持续学习中)
📚内容创作:
小红书、抖音、B站同名账号,分享嵌入式知识和日常工作,欢迎关注!
🤝商务合作/需要学习资料联系:
🛰️:nebula0419(备注:商务合作/学习资料)
修订记录
|-----|-----------|------------------------------------|
| 版本 | 修改时间 | 修改内容 |
| 1.0 | 2023.4.6 | 初稿:main 与 argc/argv |
| 2.0 | 2024.5.21 | 补充命令行传参场景说明 |
| 3.0 | 2026.3.1 | 优化排版 |
| 4.0 | 2026.7.30 | 修正 argc 遍历示例、补充小结 |
| 4.1 | 2026.8.1 | 细化 argc/argv 布局与遍历注意点,补强退出码与应用场景说明 |
一、前言
在 C 语言学习与开发中,main 是宿主环境(hosted environment,如 Linux/Windows 用户态程序)下程序的入口。独立环境(freestanding,常见于裸机启动)可能没有标准 main,由启动文件跳到自定义入口,本文以常见的 Linux / 桌面 C 程序为主。
本文将从语法格式、声明形式、argc/argv 细节入手,结合可运行示例说明命令行参数的用法。

读图要点:
- 宿主环境(Linux/桌面)入口是
main;裸机 freestanding 常由启动文件跳到自定义入口。
- 本文以常见
main为主;MCU 工程以启动文件与链接脚本为准。
二、main 函数的语法格式

读图要点:
- 返回
int:0成功,非 0 错误,可供脚本读取。
-
argc含程序名;argv是指针数组,且argv[argc] == NULL。int main(int argc, char *argv[])
{
return 0;
}
核心要素:
- 返回值类型 :
int。在 Linux 中,返回0表示正常退出,非 0 表示错误(可由调用方或脚本读取)。
- argc :
argument count,命令行参数个数(含程序名本身)。
- argv :
argument vector,指向参数字符串的指针数组;argv[argc]为NULL。
三、main 函数声明

读图要点:
- 无参用
int main(void);收参用char *argv[]或等价的char **argv。
- 不要写
int main():在 C 中表示参数未指定,规范性差。
形式一:不接收命令行参数
int main(void)
{
return 0;
}
建议使用 int main(void),不要写 int main()------后者在 C 中表示参数列表未指定,可读性与规范性较差。
形式二:接收命令行参数(两种等价写法)
int main(int argc, char *argv[])
{
return 0;
}
int main(int argc, char **argv)
{
return 0;
}
四、参数说明

读图要点:
./test 123 abc→argc=3:argv[0]程序名,其后为用户参数,末尾NULL。
- 自定义参数个数 =
argc - 1;有效下标0 ~ argc-1。
|----------------------------|-----------------|
| 参数 / 用法 | 说明 |
| argc | 参数个数,至少为 1(程序名) |
| argv[0] | 通常为程序路径或名称 |
| argv[1] ... argv[argc-1] | 用户传入的参数 |
| argv[argc] | 固定为 NULL |
自定义参数个数 = argc - 1,有效下标为 0 ~ argc-1。
五、代码示例

读图要点:
- 推荐
for (i = 0; i < argc; i++)或走到argv[i] == NULL。
- 不要先
while (argc--)再按下标用已被改掉的argc;若要递减,另存副本。
下面用下标遍历打印参数(推荐写法)。不要先 while (argc--) 再按 argc 循环------前者会改掉 argc,后者就会失效。
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
printf("argc = %d\n", argc);
for (i = 0; i < argc; i++) {
printf("argv[%d] = %s\n", i, argv[i]);
}
/* 也可写到 argv[argc]==NULL 为止 */
for (i = 0; argv[i] != NULL; i++) {
printf("via NULL: argv[%d] = %s\n", i, argv[i]);
}
return 0; /* 0 表示成功退出 */
}
编译并运行(假设可执行文件名为 test):
./test 123 abc
此时 argc 为 3,对应 ./test、123、abc。
若要边走边减计数,应另存副本,且与下标循环二选一即可:
int n = argc;
char **p = argv;
while (n--) {
printf("%s\n", *p++);
}
六、应用场景

读图要点:
- 常见用途:运行时配置、
exec传参、批量任务区间。
argv元素都是字符串,数值需自行strtol/atoi并做校验。
6.1 运行时动态配置
无需改代码重编译即可切换行为,例如:
- 日志级别:
./app debug/./app info
- 运行模式:
./server tcp/./server udp
- 文件路径:
./read_file /home/data.txt
6.2 进程启动传参
父进程通过 exec 系列函数启动子进程时,可把参数写入子进程的 argv,完成简单配置传递。
6.3 批量任务
例如 ./process_data 100 200 表示处理区间,提高复用性。
七、小结

读图要点:
return 0(或exit(0))表示成功;非 0 表示错误,便于脚本与自动化检测。
- 错误码尽量语义明确,不要随意返回随意整数。
- 宿主环境下用
int main(void)或int main(int argc, char *argv[])。
argc含程序名;argv[argc]为NULL;成功退出返回0。
- 遍历参数用下标或
argv[i] != NULL,避免先破坏argc再循环。
- 嵌入式裸机可能没有标准
main,以启动文件与链接脚本为准。