加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

extern char ** environ和extern char * environ []之间有什么区

发布时间:2020-12-13 23:54:46 所属栏目:Linux 来源:网络整理
导读:#include stdio.h#include stdlib.h#include unistd.hextern char *environ[];int main(int argc,char *argv[]){ int index = 0; char **env = environ; printf("Environment variables:n"); index = 0; while (env[index]) { printf("envp[%d]: %sn",inde
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

extern char *environ[];
int main(int argc,char *argv[])
{
    int index = 0;
    char **env = environ;
    printf("Environment variables:n");
    index = 0;
    while (env[index])
    {
        printf("envp[%d]: %sn",index,env[index]);
        ++index;
    }
    return 0;
}

输出:

Environment variables:  
envp[0]: GH#t

我想打印所有环境,但它无法正常工作.
我将extern char * environ []更改为extern char ** environ,它可以打印所有环境.
更改代码输出后:

Environment variables:
envp[0]: XDG_SESSION_ID=8
envp[1]: TERM=xterm
envp[2]: SHELL=/bin/bash
envp[3]: SSH_CLIENT=192.168.1.224 1085 22
envp[4]: SSH_TTY=/dev/pts/0
...

解决方法

我发现这些东西不可能不考虑实际内存中的内容,以及它是如何组织的.

内存中的某个地方是一堆包含环境字符串的数据块 – “foo = bar”,“hello = world”等等.让我们假设为了论证,“foo = bar”在地址100,“hello = world”在地址200.

内存中的其他位置是另一个列出这些数据块地址的数据块(通常后跟零,所以我们知道列表实际结束的位置,如果我们事先不知道大小}.所以这个块包含数据

{100,200,0}

如果我将此数据定义为char * env [],这意味着内存中有一个名为env的位置,并且该位置是实际数据块{100,0}.也就是说,env本身的数据将是数字100,它是一个环境字符串的地址. env之后的下一个位置将包含200,然后是0之后的下一个位置(好的,我正在简化一点).

如果我将数据块{100,0}定义为char **,则意味着内存中有一个名为env的位置,其中包含数据块{100,0}的地址.存储在env中的数据不是“100”(字符串的地址).它将是一个指示数据块开始的地址{1??00,0}.

在C程序中,环境实际上是一个char **,也就是说,environ不是字符串地址列表的开头,它是字符串地址列表的地址.要查看它,您可以错误地定义它,然后更正它,就像在原始代码的这个修改版本中一样:

extern char *environ[];
int main(int argc,char *argv[])
{
    int index = 0;
    char **env = (char **)environ[0];
    printf("Environment variables:n");
    index = 0;
    while (env[index])
    {
        printf("envp[%d]: %sn",env[index]);
        ++index;
    }
    return 0;
}

使用char * environ []告诉编译器(错误地)名为environ的位置开始一个指向字符串的指针列表,从那一点开始在内存中一个接一个地排列.实际上,只有确切位置环境中的数据才是相关的.我们可以将该数据视为environ [0],并将其转换为真实数据类型,这是一个char **.

char **和char * []之间的差异被侵蚀,因此C将不允许将数组传递给函数,这使得混淆.函数的所有参数都是单个数字 – 可以是整数或浮点数的基元,也可以是某个地址.如果尝试传递数组(即数据块),则会传递块开头的地址.这意味着在大多数代码中,您实际上可以使用char **和char * [],就好像它们是相同的东西.你会遇到问题 – 就像这个问题一样 – 当数据以某种方式排列在内存中时,除非程序员通过使用正确的类型声明告诉它,否则编译器无法解决这种问题.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读