命令行参数与环境变量
一、命令行参数
1. 什么是命令行参数?
在Linux终端中,执行可执行程序时,在程序名称后方追加的自定义参数,统称为命令行参数。
示例:./code a b c,其中 ./code 是可执行程序,a、b、c 就是传给程序的命令行参数。该机制允许程序在运行阶段接收外部数据,无需修改代码重新编译,极大提升程序灵活性。
2. C语言获取命令行参数
我们日常写的无参 main 函数是简化写法,C语言标准的 main 函数自带三个参数,专门用于接收命令行参数,定义如下:
int main(int argc, char *argv[], char *env[]);
2.1 核心参数功能详解
-
argc(argument count):整型参数,代表命令行参数的个数,统计包含程序名在内的所有参数总数。
-
argv(argument vector):字符指针数组,存储所有命令行参数字符串,每一个数组元素指向一个参数字符串。
-
env:环境变量指针数组,本文第二部分详细讲解。
3. 代码实操演示
3.1 测试代码
3.2 运行结果
4. 原理解析
执行指令" ./code a b c ss aa ww -- "时,系统会自动拆分参数:参数总数 argc=8,argv[0] 固定存储程序本身路径及名称,后续下标依次存储自定义参数。
本质:终端输入的整行指令,会被bash以空格为分隔符拆分字符串,存入 argv 数组,供程序读取使用。
5. 使用场景
-
简易配置:程序运行时传入标记(如开启调试模式、设置运行权限);
-
批量处理:传入多个文件路径,批量读写操作文件;
-
指令开发:Linux自带指令(ls、cp、mv)都依赖命令行参数,如
ls -l。
二、环境变量
1. 前置疑问:为什么自己写的程序要加 ./ ?
常见疑惑:系统命令ls、mkdir、pwd 可以直接输入执行,而自己编译的 code 必须写 ./code,直接输入code 会提示命令不存在。
1.1 核心原因
Linux终端(bash)执行指令时,不会全盘扫描磁盘,而是按照PATH环境变量记录的路径顺序,依次查找可执行文件:
-
系统命令:存放于PATH默认配置的系统目录(
/bin、/usr/bin),bash可自动检索; -

-
自定义程序:存放在当前工作目录,默认不在PATH路径中,bash检索不到,必须手动加路径
./(当前目录)指定位置。
2. PATH环境变量详解
PATH 是Linux最重要的环境变量,作用:存储系统指令搜索路径,多个路径用冒号 : 分隔。
查看PATH指令:echo $PATH。
2.1 错误修改PATH:直接赋值
错误写法
PATH=/...路径
问题剖析
-
该修改方式定义的是本地shell变量,不是环境变量;
-
使用
env指令无法查询到该变量,仅能用echo $PATH临时查看; -
直接赋值会覆盖原有PATH所有系统路径,导致
ls、mkdir 等系统命令全部失效。
2.2 正确修改PATH:追加路径
正确写法
PATH=$PATH:/...路径
语法解析
-
$PATH:引用原有PATH所有路径,保留系统命令检索目录;
-
::路径分隔符,追加自定义程序路径。
修改完成后,无需加 ./,直接输入 code 即可运行自定义程序,同时保留ls等系统命令。
3. PATH修改的关键特性
3.1 临时生效(内存级修改)
无论正误修改方式,终端中直接修改的PATH仅保存在内存中,属于临时修改。一旦关闭当前终端、重新连接Linux,PATH会自动还原为系统默认配置,不会永久篡改系统文件。
3.2 误修改补救方案
若错误赋值导致ls等命令失效,无需手动还原路径,直接关闭当前终端,重新打开即可。bash重启后会自动读取系统配置文件,重置PATH为默认值。
4. 常见环境变量与操作指令
4.1 常见环境变量
-
HOME:当前用户家目录,普通用户默认
/home/用户名,root用户/root; -
SHELL:当前终端解析器,默认
/bin/bash; -
HOSTNAME:主机名称。
-
USER: 当前用户名
-
PWD: 当前路径
4.2 环境变量常用指令
-
echo $变量名:打印指定环境变量,示例echo $HOME; -
env:查看系统所有环境变量; -
export:设置一个新的环境变量; -
unset 变量名:删除环境变量。 -
set: 显⽰本地定义的shell变量和环境变量;
5. 代码获取环境变量
在C语言中,Linux下一共有三种标准方式获取环境变量,分别是:main函数第三个env参数、全局变量environ、库函数getenv。下面全部实操演示,并对比三者区别,补齐知识点。
5.1 方式一:通过main()函数第三个参数 env 获取
main函数完整原型:int main(int argc, char *argv[], char *env[]);,env 是字符指针数组,专门存储全部环境变量,以NULL作为数组结束标志。
5.2 方式二:通过全局变量 environ 获取
Linux系统在libc库中定义了全局外部变量 environ,同样是环境变量指针数组。该变量没有头文件声明,使用必须手动 extern 声明。
5.3 方式三:通过系统函数 getenv() 获取(推荐)
前两种方式都是遍历全部环境变量,而 getenv() 可以精准获取指定名称的环境变量,使用最简单、开发最常用。

5.4 三种方式优缺点对比
|
获取方式 |
特点 |
优缺点 |
使用场景 |
|---|---|---|---|
|
main函数env参数 |
程序启动自动接收 |
优点:无需额外声明;缺点:只能全部遍历,无法精准查找 |
查看全部环境变量 |
|
全局变量environ |
libc全局外部变量 |
优点:不受main参数限制;缺点:需要extern声明,遍历繁琐 |
底层遍历、内核源码开发 |
|
getenv()函数 |
标准库函数 |
优点:精准查询、代码简洁、安全稳定;缺点:一次只能查一个 |
日常开发首选 |
6. 深层剖析:环境变量是谁给的?为什么程序可以获取?
当我写完三种获取代码后会产生疑问:环境变量到底是谁提供的?为什么我们写的C程序可以直接读取?数据从哪来?本节结合Linux进程底层原理,直白通俗解答。
6.1 谁给的环境变量?
最终来源:bash终端(父进程)。
-
我们在Linux操作的终端,本质是一个 bash进程;
-
系统开机登录用户时,bash会自动读取系统配置文件,加载默认环境变量(PATH、HOME、USER等);
-
我们手动使用
export创建的环境变量,也是写入当前bash进程内部; -
我们运行的C语言程序,是bash通过fork创建出来的子进程。
6.2 为什么子进程可以获取环境变量?
核心特性:环境变量具有全局属性,子进程默认继承父进程全部环境变量。
结合前文fork知识点:
-
使用
fork()创建子进程时,父子进程代码共享,数据采用写时拷贝; -
父进程bash内部维护一张环境变量表,在创建子进程瞬间,会把这张环境变量表拷贝一份给子进程;
-
所以我们的C程序(子进程)天然自带一份环境变量表,这就是能通过 env、environ、getenv 获取数据的根本原因。
6.3 底层传递流程(极简流程)
-
登录Linux,系统启动bash进程,加载系统环境变量;
-
用户在终端输入
./code,bash调用fork创建子进程(我们的程序); -
创建子进程时,bash将自身环境变量表拷贝给子进程;
-
子进程程序运行,通过三种方式读取自身内存中保存的环境变量表。
6.4 关键补充:本地变量为什么不能继承?
-
普通本地变量(如
MYENV=123不加export):仅属于当前bash内部,不会拷贝给子进程,程序读取不到,其他bash也无法访问; -
环境变量(加export修饰):标记为全局变量,fork创建子进程时强制拷贝,所有子进程均可继承。
一句话总结:环境变量由bash父进程提供,依靠fork创建进程时的继承机制传递给子进程,这就是C语言程序能读取环境变量的本质原因。
6.5 环境变量与本地变量的区别
在学习本地变量与环境变量区别之前,必须先搞懂两个概念:什么是bash内部?什么叫仅在当前bash终端生效?只有弄懂作用域,才能彻底分清两种变量。
0、前置科普:通俗易懂理解bash终端
-
什么是bash?我们打开的Linux终端,每一个窗口都是一个独立的bash进程,系统会给每一个bash分配唯一PID。
-
什么叫bash内部?每一个bash进程都有自己独立的内存空间,在该终端定义的变量,存放于当前bash进程内存内部。
-
什么叫仅在当前bash终端?变量只能在定义它的这一个终端内使用,新开一个终端、切换窗口,变量直接消失看不到。
0.1 验证
-
打开终端A,定义本地变量:
MYNAME=zhangsan; -
在终端A输入
echo $MYNAME,可以正常打印变量; -
新建终端B,同样输入
echo $MYNAME,无任何输出; -
原因:本地变量只存在终端A的bash内存内部,终端B是另一个独立bash,完全看不到。
0.2 通俗人话比喻
-
每一个bash终端 = 一间独立房间;
-
本地变量 = 房间私有物品,只在这间房能用,别的房间看不见;
-
环境变量(export) = 公共物品,不仅自己房间能用,自己生的孩子(子进程)也能使用。
在Linux Shell中,变量分为本地变量(临时变量)和环境变量(全局变量)。
1、定义概念
-
本地变量:仅定义在当前bash终端的变量,不会被其他进程识别,不具备继承性。
-
环境变量:被export修饰、挂载到进程环境表中的变量,具有全局属性,可以被子进程继承。
2、创建方式区别
# 1.定义本地变量(无export) MYENV="123" 不进入环境变量表
# 2.定义环境变量(带export) export MYENV="321" 进入环境变量表

3、核心区别汇总表
|
对比维度 |
本地变量 |
环境变量 |
|
创建语法 |
变量名=值 |
export 变量名=值 |
|
作用范围 |
仅当前bash终端 |
当前bash + 所有子进程 |
|
能否被子进程继承 |
不能 |
可以 |
|
查看命令 |
可以用set、echo $查看 |
env、echo $、set 都能查看 |
|
生命周期 |
关闭终端立即销毁 |
关闭终端立即销毁(内存级) |
|
是否进入环境变量表 |
不进入 |
进入,可被C程序getenv读取 |
4、实验现象
-
只写
MYENV=123:本地变量,C语言程序读取不到; -
加上
export MYENV=321:升级为环境变量,子进程程序可以读取; -
无论哪种写法,重启终端全部消失,都是临时变量。
5、一句话通俗总结
本地变量只给自己(当前bash)用,环境变量全家(子进程)都能用;export就是把私有变量改成公有变量的指令。
6、bash内部维护两张表
每一个bash进程内存内部,天然维护两张独立的变量表,这是变量区分的底层本质:
-
第一张:环境变量表:存放被export修饰的变量,支持子进程继承,使用 env、echo 指令可以查看。
-
第二张:本地变量表(Shell私有变量表):存放无export修饰的普通变量,仅当前bash使用,不支持继承,env无法查看。
指令区分口诀: 1、env:只打印第一张表(环境变量); 2、set:同时打印两张表(本地变量+环境变量)。
7、拓展区分:进程层面的两张表
站在我们编写的程序(子进程)角度,进程内存中也存在两张表,不要和bash两张表混淆:
-
argv[] 命令行参数表:存放执行程序时传入的参数;
-
env[] 环境变量表:从bash父进程继承过来的环境变量。
三、拓展注意事项
若想要永久修改环境变量(重启终端不失效),需要修改系统配置文件 ~/.bashrc 或 /etc/profile,在文件末尾写入export修改指令,执行source 配置文件 生效。但不建议随意修改系统级配置文件,优先使用临时修改方式。
3.1 补充:什么是配置文件?
1、什么是bash配置文件?
配置文件本质:Linux给bash终端准备的开机自动执行的记事本。
-
每当你打开一个新终端,bash进程启动;
-
bash启动第一件事:自动读取专属配置文件;
-
文件里面写满了指令、自定义环境变量、PATH路径;
-
读到什么,bash就初始化什么。
2、为什么修改配置文件可以永久生效?
-
终端直接export:修改写在内存里,关闭终端,内存释放,全部消失(临时);
-
修改配置文件:修改写在硬盘文件里,永久保存;每次新开终端,bash自动重读文件,自动加载你的PATH、自定义变量(永久)。
3、两个最常用配置文件区别
|
配置文件 |
路径 |
作用范围 |
适用人群 |
|
用户级配置文件 |
~/.bashrc |
仅当前普通用户生效 |
日常开发、个人配置(推荐) |
|
系统级配置文件 |
/etc/profile |
所有用户全部生效 |
管理员root、系统全局配置 |
4、source命令是什么?
修改配置文件后,不会立刻生效,因为当前bash不会自动重读文件。
source 文件名:强制让当前终端立刻重新读取配置文件,不用重启终端。
示例:source ~/.bashrc
5、极简总结
-
配置文件 = bash开机自启动脚本;
-
写在终端:内存临时生效;
-
写在配置文件:硬盘永久保存,重启终端不丢失;
-
source:手动刷新配置,不用重启终端。
四、全篇总结
4.1 命令行参数总结
-
命令行参数是程序运行时,在终端传入的自定义参数,bash以空格拆分参数;
-
main函数参数:argc为参数个数、argv为参数字符串数组,argv[0]永远保存程序名;
-
作用:无需修改代码,在外部向程序传递数据,Linux系统指令均依赖命令行参数实现功能。
4.2 环境变量核心总结
-
自定义程序需要加 ./ 执行,是因为当前目录不在PATH默认搜索路径中;系统命令无需加路径,存放在PATH系统目录;
-
PATH错误写法:直接赋值,覆盖系统路径导致命令失效;正确写法:export PATH=$PATH:路径,追加路径;
-
终端修改PATH属于内存级临时修改,关闭终端自动还原。
4.3 本地变量 & 环境变量总结
-
每一个Linux终端都是独立bash进程,变量默认存放在当前bash内存中;
-
本地变量:无export修饰,仅当前bash可用,不能被子进程继承,只能set查看;
-
环境变量:export修饰,存入环境变量表,可被子进程继承,env、echo、set均可查看;
-
本质区别:本地变量私有,环境变量共享。
4.4 C语言三种获取环境变量方式
-
main函数env参数:适合遍历所有环境变量,无需额外声明;
-
environ全局变量:底层使用,需要手动extern声明;
-
getenv函数:开发首选,精准查询单个环境变量,代码简洁;
-
共性:所有环境变量全部由父进程bash继承而来,依靠fork拷贝传递。
4.5 配置文件总结
-
配置文件是bash开机自启动脚本,新开终端自动读取;
-
终端修改变量:保存在内存,临时生效;修改配置文件:写入硬盘,永久生效;
-
用户级
~/.bashrc仅个人生效,系统级/etc/profile所有用户生效; -
source命令:手动刷新配置文件,无需重启终端即可生效。
4.6 底层本质一句话汇总
bash作为父进程,自身维护环境变量表,通过fork创建子进程时拷贝环境变量;我们编写的程序本质是子进程,因此可以读取环境变量;而export指令,就是将私有本地变量升级为可继承的公有环境变量。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)