.xmind
和
.png
文件都已同步导入至
资源
在谈环境变量之前,我们先来看看命令行参数这一概念
一般来说,我们的主函数main
都是不带参的:
int main(){}
但是相信不少小伙伴也见过这种带参形式的main
函数:
int main(int argc, char* argv[]){}
argv
是一个指向多个字符串的指针数组,最后一个元素为NULL
argc
则表示指针数组argv
有效元素的个数我们可以来看一个例子:
#include <stdio.h> int main(int argc, char* argv[]) { for (int i = 0; i < argc; i++) printf("%s\n", argv[i]); return 0; }
形成可执行文件
mybin
后,我们执行命令:./mybin -l
output:
./mybin -l
可以看到,这个程序将我们在命令行输入的命令./mybin -l
,利用空格将其分为了两个字符串./mybin
和-l
,并将其存放在了数组argv
中,对于./mybin
和-l
这种执行命令用到的参数,我们就叫作命令行参数,而对其进行存储的数组argv
,就称为命令行参数列表
可能有小伙伴会问:命令行参数有什么用?
我们不妨来回忆一下以前学过的关于Linux命令的知识:
Linux的各种命令也是一个个的可执行程序,我们可以利用各种选项来实现不同的功能
例如,命令
ls
用来查看当前目录的内容。如果加上选项-l
,就可以知道目录所属文件或目录的详细信息,加上选项-a
就可以查看隐藏文件,其不同的选项都对应着不同的功能。和上面的命令行参数做对比,我们惊奇的发现**
ls
的选项-a
、-l
等不也是一个个命令行参数吗**?正是因为有了命令行参数,我们才可以让ls
等命令根据不同的选项来执行不同的功能。
我们可以利用命令行参数来写一个能实现加、减、乘的简单计算器:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
if (argc != 4)
{
printf("Usage:\n\t%s -[add|sub|mul] x y\n\n", argv[0]);
return 1;
}
int x = atoi(argv[2]);
int y = atoi(argv[3]);
if (strcmp(argv[1], "-add") == 0)
printf("%d\n", x + y);
else if (strcmp(argv[1], "-sub") == 0)
printf("%d\n", x * y);
else if (strcmp(argv[1], "-mul") == 0)
printf("%d\n", x - y);
else
printf("unknown!\n");
return 0;
}
效果如下:
尽管上面的命令已经和ls
的执行方法很像,但细心的小伙伴还是能发现不同点:
虽然ls
这个命令也是可执行程序,但是为什么我们运行使用的时候不需要./
来运行,而是可以直接使用它的名字来运行呢?
我们应该清楚,要执行一个可执行程序,首先就要知道这个程序具体在那个位置
因此,
./filename
实际上是一个相对路径,表示当前目录的filename
文件,用来告诉系统这个可执行程序在哪个地方既然可以用相对路径,绝对路径也同样可以执行一个可执行程序:
因此,我们可以做出假设:既然执行
ls
命令不用输入它的路径,那么操作系统肯定已经提前知道了它的路径
上面的假设显然是成立的,像ls
这种bash
命令的路径都已经存放在了一个名为PATH
的环境变量中
我们可以用命令:echo $PATH
来进行查看:
同样,我么可以将自己写的可执行程序也加入PATH
变量中来达到相同的效果
命令:
PATH=程序所在路径:$PATH
注意:
:$PATH
一定不能省略,将程序所在路径添加到PATH
就变为了将PATH改为程序所在路径
。这明显是不同的- 如果这么做了,
bash
命令很可能就不能使用了;但也不要过于紧张,重新启动一次bash
环境变量就会和原来一样了
演示:
概念:
- 顾名思义,环境变量也是变量,是系统内置的具有特殊用途的变量
- 环境变量不是一个,而是一堆。除了上面提到的
PATH
,还有USER
、HOME
等环境变量
查看所有环境变量:
env
查看单个环境变量:
echo $name
命令:
export name=
命令:
unset name
方法一:
利用main
函数的形参int main(int argc, char* argv[], char* env[])
env
也是一个字符指针数组,存储着所有的环境变量env
也是以NULL
结尾的例如:
#include <stdio.h>
int main(int argc, char* argv[], char* env[])
{
//作用相当于命令"env",打印出所有的环境变量
for (int i = 0; env[i]; i++)
printf("%s\n", env[i]);
return 0;
}
方法二:
利用函数getenv()
获取指定的环境变量
头文件:
<stdlib.h>
函数原型:
char *getenv(const char *name);
例如:
#include <stdio.h>
#include <stdlib.h>
int main()
{
const char* ret = getenv("PATH");
printf("%s\n", ret);
return 0;
}
output:
/opt/rh/devtoolset7/root/usr/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/LWJ/.local/bin:/home/LWJ/bin
方法三:
利用宏environ
需要包含头文件:
<unistd.h>
如果要用,首先要对这个变量进行引用:
extern char** environ
例如:
#include <stdio.h>
#include <unistd.h>
int main()
{
extern char** environ;
//和命令"env"一样,打印出所有的环境变量
for (int i = 0; environ[i]; i++)
printf("%s\n", environ[i]);
return 0;
}
在代码中,我们也可以利用函数putenv()
来修改或者添加环境变量:
头文件:
<stdlib.h>
函数原型:
int putenv(char *string);
注意:
string
的内容应该类似于name=value
这种形式,以符合规范
例如:
#include <stdio.h>
#include <stdlib.h>
int main()
{
putenv("TEST=6666666");
printf("%s\n", getenv("TEST"));
return 0;
}
output:
6666666
环境变量是可以被继承的
- 子进程以父进程为模板创建,因此子进程的环境变量也应该和父进程一样。例如上面的的
main
函数的参数中的环境变量就是继承的父进程bash
的- 又例如上面的函数
putenv()
,它会改变本进程和其所属子进程的环境变量但是不会影响它的父进程的环境变量
环境变量是内存级的
- 作为一个变量,每一次关闭
bash
,环境变量都会被作为一种资源被释放- 环境变量都存储在磁盘的文件中:每个用户都有一个
.bash_profile
隐藏文件用来记录环境变量- 每一次重新打开
bash
,系统都会从这个文件中读取环境变量,并写入内存
我么可以直接向这个文件中写入需要的环境变量,这样当我们打开
bash
时,系统就会自动生成这个变量了。
设置本地变量:
命令:
name=value
例如:
查看本地变量:
命令:
set
- 该命令用于查看所有的变量,包括环境变量和本地变量
env
不能用于查看本地变量
演示:
bash
内部使用本篇完