【C语言】09-深入解析main函数

作者简介

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 函数的语法格式

读图要点:

  • 返回 int0 成功,非 0 错误,可供脚本读取。
  • argc 含程序名;argv 是指针数组,且 argv[argc] == NULL

    int main(int argc, char *argv[])
    {
    return 0;
    }

核心要素:

  1. 返回值类型int。在 Linux 中,返回 0 表示正常退出,非 0 表示错误(可由调用方或脚本读取)。
  1. argcargument count,命令行参数个数(含程序名本身)。
  1. argvargument 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 abcargc=3argv[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,对应 ./test123abc

若要边走边减计数,应另存副本,且与下标循环二选一即可:

复制代码
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,以启动文件与链接脚本为准。
相关推荐
Dxy12393102162 小时前
Linux 编译安装 Python 3.12.10(多版本共存,不破坏系统Python)
linux·运维·python
神罚天下ET3 小时前
c# ACME client (补充)
开发语言·c#
小灰灰搞电子3 小时前
Qt 实现魔法导航菜单源码分享
开发语言·qt
天空'之城3 小时前
C 语言工业级通用组件手写 23:卡尔曼滤波(简易版)
c语言·卡尔曼滤波·嵌入式算法·工业级组件
持敬chijing3 小时前
Python概述
开发语言·python
xz驱动分享3 小时前
Linux DMA 子系统学习笔记
linux·dma·rk3588·嵌入式软件
888CC++4 小时前
C语言与C++的区别:从面向过程到面向对象
java·c语言·c++
w67820074 小时前
Prisma不能优雅的支持DTO,试试Vona ORM吧
linux·运维·ubuntu
与你4035 小时前
STM32 MQTT协议详解:从报文地狱到阿里云实战
嵌入式