文章目录

  • 专栏导读
  • 文章导读
    • 引例1
    • 引例2
  • 认识环境变量
      • 环境变量的概念
      • 常见的环境变量
      • 和环境变量相关的指令
  • main函数的第三个参数
      • 如何通过代码获取环境变量
        • 方法一 使用参数获取
        • 方法二 使用全局变量获取
        • 方法三 使用系统调用获取(最实用)
      • 环境变量的全局属性
        • 证明
  • 命令行参数
        • Demo
    • 有什么用?

专栏导读

作者简介:花想云 ,在读本科生一枚,C/C++领域新星创作者,新星计划导师,阿里云专家博主,CSDN内容合伙人…致力于 C/C++、Linux 学习。

专栏简介:本文收录于 Linux从入门到精通,本专栏主要内容为本专栏主要内容为Linux的系统性学习,专为小白打造的文章专栏。

相关专栏推荐:C语言初阶系列C语言进阶系列C++系列数据结构与算法

文章导读

你知道main函数有几个参数呢?你使用过它们吗?本章我们就一起来认识一下main函数的几个不常见但是作用很大的参数~

引例1

在Linux中,当我们生成一个可执行程序后一般要使用./ + 文件名的方式运行(./为文件的路径)。我们应该知道例如ls、pwd、touch等这些指令其实都是一个个可执行程序,那么为什么ls在执行的时候不需要用到./呢?

还有ls在执行的时候还可以添加一些参数呢?例如:ls -als -l等。那么我们自己生成的程序能否做到呢?

引例2

在你的印象中,C语言中的main函数有参数吗?有几个参数呢?你是否见过这样的场景:

#includeint main(int argc,char* argv[],char* envp[]){printf("myprocess\n");return 0;}

如果你见过,那么你清楚这些参数该怎么使用吗?

认识环境变量

环境变量的概念

  • 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数;

常见的环境变量

常见的环境变量有这些(我们可以使用$+环境变量名来查看环境变量的值):

  • PATH:指定命令的搜索路径;

假若我们也想将自己的程序像ls那样不指定路径就可以执行该怎么做呢?使用命令:

$ export PATH=$PATH:文件名

如上图所示,当我们把可执行程序的路径添加到环境变量PATH中以后,就可以直接使用文件名来执行程序了。

第二种方法

除了上面那种方法我们还可以将可执行程序拷贝到指定目录下(记得要以root的身份):

$ cp -rf 文件名 /usr/bin

除了PATH以外,还有其它环境变量例如: HOMEPWD等等。

或者使用指令 env 查看所有的环境变量:

和环境变量相关的指令

  • echo: 显示某个环境变量值;
  • export: 设置一个新的环境变量;
  • env: 显示所有环境变量;
  • unset: 清除环境变量;
  • set: 显示本地定义的shell变量和环境变量;

main函数的第三个参数

引例中提到了main函数是有参数的,我们首先来看看main函数的第三个参数——envpenvenvironment(环境)的缩写,猜一下它应该和环境变量有些关系。

首先我们可以观察到envp是一个指针数组的类型,它其实是一个表结构,这张表中的内容就是一个个的环境变量。


环境变量表是一个字符指针数组,每个指针指向一个以’\0’结尾的环境变量字符串。且该表的结尾必须为NULL

如何通过代码获取环境变量

方法一 使用参数获取

第一种方式,我们可以遍历main函数提供的这张环境变量表。代码如下:

#includeint main(int argc,char* argv[],char* envp[]){for(int i = 0; envp[i]; ++i){printf("envp[%d] = %s\n",i,envp[i]);}return 0;}

方法二 使用全局变量获取

除了参数,库还为我们提供了一个全局变量environ。该变量是char**类型,其实就如同envp一样,使用方法也相同。

  • libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中,所以在使用时要用extern声明。
#includeint main(int argc,char* argv[],char* envp[]){extern char** environ;for(int i = 0; environ[i]; ++i){printf("environ[%d] = %s\n",i,environ[i]);} // for(int i = 0; envp[i]; ++i) // { // printf("envp[%d] = %s\n",i,envp[i]); // }return 0;}

方法三 使用系统调用获取(最实用)

我们还可以使用系统调用getenv来获取指定的环境变量,这种方法也是最实用的方法。

#include#include#includeint main(int argc,char* argv[],char* envp[]){char* path = getenv("PATH");if(path == NULL)perror("getenv");else printf("%s\n",path);return 0;}

环境变量的全局属性

  • 环境变量通常具有全局属性,可以被子进程继承下去;

证明

当一个程序变成进程,他的父进程就是bash。那么我们如果将某个环境变量添加到bash的环境变量表里面,该进程能够使用吗?结果如下:

#include#include#includeint main(int argc,char* argv[],char* envp[]){char* myenv = getenv("HELLO");if(myenv == NULL)perror("getenv");else printf("%s\n",myenv);return 0;}

命令行参数

认识了main函数中的一个参数。其它两个也就非常容易理解了。在引例中我们提到,为什么ls在执行时可以使用-a、-l等选项,我们平时写的程序怎么不需要呢?

其实main函数为我们提供了这个功能,我们只是平时不太用而已。

Demo

写一个程序测试一下我们能否使用命令行参数:

#include#include#includeint main(int argc,char* argv[],char* envp[]){for(int i = 0; i < argc; i++){printf("argc: %d,argv[%d]=%s\n",argc,i,argv[i]);}return 0;}

有什么用?

我们看到了命令行参数的使用,那么我们平时该怎么使用呢?

我们可以使程序根据不同的命令行参数执行不同的内容从而达到一个程序多种使用的效果。例如:

  • 设计一个计算器,要求可以根据不同的选项完成不同的计算;
#include#include#includevoid Usage(const char* name){printf("\nUsage:%s -[+][-][*][/]\n\n",name);exit(-1);}int main(int argc,char* argv[],char* envp[]){if(argc!=2) // 必须指定输入一个参数Usage(argv[0]);int n1 = 0;int n2 = 0;int ret = 0;printf("-----num1 = ");scanf("%d",&n1);printf("-----num2 = ");scanf("%d",&n2);if(strcmp(argv[1],"-+")==0) ret = n1 + n2;else if(strcmp(argv[1],"--")==0) ret = n1 - n2;else if(strcmp(argv[1],"-*")==0) ret = n1 * n2;else if(strcmp(argv[1],"-/")==0) ret = n1 / n2;printf("\n-----resault = %d\n",ret);return 0;}

本章的内容就到这里了,觉得对你有帮助的话就支持一下博主把~

点击下方个人名片,交流会更方便哦~
↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓