c-可以生成多少个参数以及为什么生成这些参数



我正在使用此代码。。。

#include <stdio.h>
int main(int argc,char *argv[]){
    int i =0;
    if (argc == 1){
        printf("You have entered 1 argument and you suck n");
    }
    else if (argc > 1 && argc<4){
        for (i=0;i<4;i++){
            printf("you have entered the following args %d.%s n",(i),argv[i]);
        }
        printf("n");
    }
    else{
        printf("You have entered more than four arguments and you suck.n");
    }
    return 0;
}

如果我将for循环从for (i=0;i<4;i++)更改为for (i=0;i<7;i++),我会得到以下输出:

cam@cam:~/Desktop/D/c/c-code$ ./ex12 hi there 
you have entered the following args 0../ex12 
you have entered the following args 1.hi 
you have entered the following args 2.there 
you have entered the following args 3.(null) 
you have entered the following args 4.XDG_VTNR=7 
you have entered the following args 5.LC_PAPER=en_IN.UTF-8 
you have entered the following args 6.ORBIT_SOCKETDIR=/tmp/orbit-cam 

为什么没有错误?为什么要生成这些与我的操作系统相关的变量?

越界访问数组会导致未定义的行为。未定义行为的后果是未定义。纯属巧合,你碰巧正在读取一些环境变量。在其他系统上,或在此类行为的其他示例中,您可能会意外地读取其他信息(请参阅heartsleed了解一个显著的示例),或意外地导致segfault(崩溃)。。。然而,所有这些结果都纯属巧合,不可依赖。

Unix系统上程序的正常内存布局是,指向程序参数的指针数组后面紧跟着指向环境变量的指针数组。

您正在做的是超越参数指针数组(注意argv[argc]处有一个空指针),进入环境指针数组,该数组也由一个空指示器终止。

未定义的行为

因为您正在超越argv数组的末尾,所以您正在调用未定义的行为。这很危险:任何事情都有可能发生。不过,有时结果是好的——你永远不能依赖它。

有了强制性免责声明,您可以使用以下代码获得环境的完整转储。但是,必须理解C标准不能保证清楚标记线之后的行为(POSIX也不能)。

main()的额外envp自变量在C标准的附录J.5.1中作为一个通用扩展进行了说明,该扩展由Microsoft Windows和Unix系统支持。

J.5.1环境论点

在托管环境中,main函数接收第三自变量char *envp[],指向指向char的以null结尾的指针数组,每个指针指向一个字符串为程序的执行提供有关环境的信息(5.1.2.2.1).

这不是标准规定的;它被标准认可为通用的。在POSIX系统上,还可以通过全局变量char **environ获取环境变量。而且,如果使用setenv()putenv()操作环境,则无法保证存储在environ中的值与传递给main()envp中存储的值保持相同。

#include <assert.h>
#include <stdio.h>
int main(int argc, char **argv, char **envp)
{
    int i;
    printf("Argc: %dn", argc);
    for (i = 0; i < argc; i++)
        printf("Arg[%d]: <<%s>>n", i, argv[i]);
    assert(argv[argc] == 0);
    assert(argv[i] == 0);
   /* Print the environment cleanly on most systems */
    char **ep;
    for (ep = envp; *ep != 0; ep++)
        printf("Env[%d]: <<%s>>n", (int)(ep - envp), *ep);
    printf("Number of environment variables: %dn", (int)(ep -envp));
    /* From here on, neither the C standard nor POSIX guarantees anything */
    /* In practice, it works on Unix systems; I don't know about Windows */
    assert(&argv[argc+1] == envp);
    for (i++; argv[i] != 0; i++)
        printf("Env[%d]: <<%s>>n", i - argc - 1, argv[i]);
    printf("Number of environment variables: %dn", i - argc - 1);
    return 0;
}

请注意,即使Windows支持main()的第三个参数,也不能保证它指向的内存紧跟在argv指向的内存之后(尽管发现它与Unix上的布局相同也就不足为奇了)。从技术上讲,在Unix上不能保证envp数组紧跟在argv数组之后;然而,我从来没有遇到过这样的系统。

env程序允许您为它运行的命令设置环境,而-i选项将忽略任何继承的环境。这允许我运行上面的代码(编译成程序ev2),如下所示:

$ env -i HOME=/home/elephant PATH=/home/elephant/bin:/bin:/usr/bin TZ=US/Pacific 
>     ./ev2 hello world
Argc: 3
Arg[0]: <<./ev2>>
Arg[1]: <<hello>>
Arg[2]: <<world>>
Env[0]: <<HOME=/home/elephant>>
Env[1]: <<PATH=/home/elephant/bin:/bin:/usr/bin>>
Env[2]: <<TZ=US/Pacific>>
Number of environment variables: 3
Env[0]: <<HOME=/home/elephant>>
Env[1]: <<PATH=/home/elephant/bin:/bin:/usr/bin>>
Env[2]: <<TZ=US/Pacific>>
Number of environment variables: 3
$

不会"生成"任何额外的参数。相反,由于C没有边界检查(与其他一些语言不同),您访问了数组边界之外的内存,而数组边界恰好是环境变量。

相关内容

  • 没有找到相关文章

最新更新