3.环境变量的意义
我们拿ls 指令举例:
我们发现,ls 后的指令为什么不需要./
,而是直接输入文件名就行了呢?也就是为什么ls就知道这个文件的当前路径在哪里呢?
实际上,这是因为我们有一个环境变量PWD,通过PWD就能够找到对应的路径:
我们发现,当我们cd ..
到什么路径,PWD就会变成什么路径。因此,ls 就是通过这个环境变量找到了这个文件。
既然环境变量中有PWD,那我们也可以自己实现PWD指令:
#include<stdio.h> #include<stdlib.h> #define PWD "PWD" int main() { printf("PWD = %s",getenv(PWD)); return 0; }
如果我们将mycmd拷贝到根目录,那么其就可以变成和pwd一样的功能。
因此,环境变量的意义就在于其可以找到指定文件的路径。环境变量就相当于系统启动时加载到内部的全局变量。
最后别忘了将拷贝的文件删掉。
4.命令行参数
4.1什么是命令行参数?
在开始之前,大家回想一下,有的编译器中的main函数中存在着这样的参数:
比如上面的DevC++中,main()中有着整形的argc参数和指针数组的argv参数,事实上,这两个参数这就是我们这一节中的主角:命令行参数。
那这个所谓的命令行参数到底是个什么鬼东西?有什么作用?能用来做什么呢?有的编译器怎么就没有呢?接下来开始演示:
1. 预备工作:
在演示之前,我们要对其进行准备工作,也就是设置一下Makefile以及程序的代码:
Makefile:
在这里,我们可以通过$
脚本语言来改变之前的代码风格,即第一个$
后的@
代表生成的mycmd
,第二个$后的^代表依赖项mycmd.c
。而后面的std=c99就是我们演示此命令行参数的必须的指令,只有在c99环境下才能成功编译。
mycmd.c:
#include<stdio.h> #include<stdlib.h> int main(int argc, char* argv[]) { for(int i=0; i < argc; i++) { printf("argv[%d]->%s\n",i, argv[i]); } return 0; }
2. 演示命令行参数:
在程序中加上命令行参数之后,我们以打印的方式看看究竟它对应的是什么东西。执行:
我们可以发现,所打印的结果,就是对应的命令行中的命令以及选项,因此我们也知道了为什么叫做命令行参数:
但main函数是程序的入口,那么是谁调用了main函数呢?谁又将命令行参数传给了main函数呢?事实上这些都是shell和操作系统所做出的行为。因此有的编译器中没有并不是真的没有,而是隐藏在相关的位置,操作系统同样会通过命令行参数去通过命令调用这个程序。
4.2 命令行参数的作用
首先,对于我们上面所演示的两个命令行参数,具体有什么作用呢?那我们通过程序看一下:[mycmd.c]
#include<stdio.h> #include<stdlib.h> #include<string.h> // ./mycmd /-a /-b /-c // ./mycmd -ab/-ac/-bc int main(int argc, char* argv[]) { if(argc != 2) { printf("Usage: \n\t%s [-a/-b/-c/-ab/-ac/-bc/-abc]\n", argv[0]); } if(strcmp("-a", argv[1]) == 0) { printf("功能a\n"); } if(strcmp("-b", argv[1]) == 0) { printf("功能b\n"); } if(strcmp("-c", argv[1]) == 0) { printf("功能c\n"); } if(strcmp("-ab", argv[1]) == 0) { printf("功能ab\n"); } if(strcmp("-bc", argv[1]) == 0) { printf("功能bc\n"); } return 0; }
我们通过这样列出几个选项之后,我们就可以进行如下执行:
我们发现,即通过命令行参数的加入,我们可以通过一个程序的不同选项去实现他不同的功能,那么这就是命令行参数的作用。我们也就知道了对于ls一类的程序是如何通过选项从而去执行不同命令的。
事实上,对于这种【通过不同选项执行一个程序的不同功能】的方式,在windows也可以去执行,当我们通过win+R
快捷方式打卡windows的终端,我们输入shutdown /?
就可以看到shutdown不同选项所对应的不同功能:
我们随便用两种选项举例:1.shutdown -s -t 360
: 电脑在360秒后自动关机:
通过shutdown -a
终止这个程序发生,阻止6分钟后关机。
(自己也可以动手试一下)
1. 第三个命令行参数env
当我们明白前两个命令行参数的作用时,事实上还有第三个命令行参数:env。我们知道,env命令能够查看环境变量,在命令行参数中,env也是指针数组类型,因为环境变量实际上也都是一个个的字符串,而最后一个字符串实际上就是NULL,也就是0,因此我们在编辑代码时可以用这个作为截止条件:
#include<stdio.h> #include<stdlib.h> #include<string.h> int main(int argc, char* argv[]) { for(int i=0; env[i]; i++) { printf("env[%d]: %s\n", i, env[i]); } return 0; }
那我们执行一下这个程序:
我们发现所有的环境变量都通过这个程序显示出来,这也就代表着env这个命令行参数确实将环境变量传入了程序中。
2. 验证命令行参数env
那为了验证这个env会将环境变量都传入到程序中,我们就新建一个环境变量export myval=4444
,观察运行结果:
我们在众多环境变量中发现了myval。
3. 其他显示环境变量的方法
我们知道,除了通过命令行参数显示之外,我们也可以通过getenv获取,但是我们需要明白一件事情,env命令行参数这个指针数组是从哪里传入的环境变量呢?
事实上,env是通过C语言中第三方environ获取的,而environ本身作为二级指针保存,我们知道指针数组和二级指针可以通过解引用的方式相互转换,这也就恰恰对应了可以把environ中的内容一一传递给env,那么我们通过: man environ查看其需要的头文件并演示代码程序:
程序【mycmd.c
】:
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> int main() { extern char** environ; //声明从文件中获取environ变量 for(int i = 0; environ[i]; i++) { printf("environ[%d]: %s\n", i, environ[i]); } return 0; }
结果:
我们同样也能通过这种方法获取到环境变量。
因此,我们知道在进程上下文中三种获取环境变量的方式:
getenv
函数获取、命令行参数char* env[]
获取,第三方extern char** environ
获取。其中推荐的是getenv获取,因为可以指定获取。
5.总结环境变量
通过上面的描述,我们知道,环境变量就是操作系统启动之后将内部内容加载到内存中的变量,也就是全局变量。通过环境变量,我们可以对一些所需要的环境进行配置。