是“的argv [0] =名称的可执行”的公认标准或只是一个常见的约定?是“的argv [0] =名

2019-05-08 22:13发布

当传递参数到main()在C或C ++应用程序,将argv[0]永远是可执行文件的名称? 或者这仅仅是一个常见的约定,并且不保证是真实的100%的时间?

Answer 1:

猜测(即使是受过教育的猜测)很有趣,但你真的需要去到标准文件,以确保万无一失。 例如,ISO C11的状态(我的重点):

如果值argc大于零,则该字符串被指向argv[0] 表示节目名称; argv[0][0]应为空字符,如果程序名称不能从主机环境。

所以,不,这只是程序的名称,如果该名称可用。“代表”的节目名称,不一定程序名称。 ,指出之前的部分:

如果值argc大于零,阵列成员argv[0]通过argv[argc-1]包括应包含指向字符串,其通过编程启动之前的主机环境给定实现所定义的值。

这是C99,以前的标准不变,意味着即使不按标准规定-它是由完全的执行。

这意味着,节目名称可以是空的,如果如果主机环境确实提供了它的主机环境并没有提供它,别的,规定“任何东西”在某种程度上代表了程序名称。 在我更残暴的时刻,我会考虑它翻译成斯瓦希里语,通过替代密码运行它,然后它是反向字节顺序存储:-)。

然而,实现定义确实有在ISO标准的具体含义-实施必须证明它是如何工作的。 因此,即使UNIX,它可以把任何东西它喜欢到argv[0]exec调用的家庭,必须(和做)文件就可以了。



Answer 2:

*nix类型系统exec*()调用, argv[0]将是任何呼叫者是置于argv0点在exec*()调用。

外壳采用的惯例,这是程序名,和其他大多数程序遵循相同的惯例,这样argv[0]通常的程序名。

但流氓的Unix程序可以调用exec()使argv[0]什么是喜欢,所以不管C标准说什么,你不能在时间这个100%计算。



Answer 3:

根据C ++标准,3.6.1节:

的argv [0]应为指针NTMBS的初始字符,表示用来调用该程序或“”名称

所以,不,它不能保证,至少标准。



Answer 4:

本页面的状态:

元素的argv [0]通常包含了程序的名字,但这应该不依赖于此 - 无论如何,它是不寻常的程序不知道自己的名字!

然而,其他页面似乎备份的事实,它始终是可执行文件的名称。 这一个规定:

你会注意到的argv [0]是程序本身的路径和名称。 这使得程序发现关于自身的信息。 它也增加了一个更的程序参数阵列,所以共同的误差时,取命令行参数是抓住的argv [0],当你想的argv [1]。



Answer 5:

ISO-IEC 9899规定:

5.1.2.2.1计划启动

如果值argc大于零,则该字符串指向argv[0]表示PROGRAMNAME; argv[0][0]应为空字符,如果程序名称不能从主机环境。 如果值argc是大于一,琴弦所指向argv[1]通过argv[argc-1]代表的程序参数

我以前也用过:

#if defined(_WIN32)
  static size_t getExecutablePathName(char* pathName, size_t pathNameCapacity)
  {
    return GetModuleFileNameA(NULL, pathName, (DWORD)pathNameCapacity);
  }
#elif defined(__linux__) /* elif of: #if defined(_WIN32) */
  #include <unistd.h>
  static size_t getExecutablePathName(char* pathName, size_t pathNameCapacity)
  {
    size_t pathNameSize = readlink("/proc/self/exe", pathName, pathNameCapacity - 1);
    pathName[pathNameSize] = '\0';
    return pathNameSize;
  }
#elif defined(__APPLE__) /* elif of: #elif defined(__linux__) */
  #include <mach-o/dyld.h>
  static size_t getExecutablePathName(char* pathName, size_t pathNameCapacity)
  {
    uint32_t pathNameSize = 0;

    _NSGetExecutablePath(NULL, &pathNameSize);

    if (pathNameSize > pathNameCapacity)
      pathNameSize = pathNameCapacity;

    if (!_NSGetExecutablePath(pathName, &pathNameSize))
    {
      char real[PATH_MAX];

      if (realpath(pathName, real) != NULL)
      {
        pathNameSize = strlen(real);
        strncpy(pathName, real, pathNameSize);
      }

      return pathNameSize;
    }

    return 0;
  }
#else /* else of: #elif defined(__APPLE__) */
  #error provide your own implementation
#endif /* end of: #if defined(_WIN32) */

然后你只需要解析字符串从路径中提取可执行文件的名称。



Answer 6:

具有应用argv[0] !=可执行文件名

  • 许多弹确定它们是否通过检查登录shell argv[0][0] == '-' 。 登录shell有不同的属性,特别是他们采购了一些默认的文件,如/etc/profile

    它通常是init本身或getty ,增加了领先-也看到: https://unix.stackexchange.com/questions/299408/how-to-login-automatically-without-typing-the-root-username-or -password-在建造/ 300152#300152

  • 多方通话的二进制文件,也许是最显着的Busybox 。 这些符号链接多个名称例如/bin/sh/bin/ls到单个exebutable /bin/busybox ,其识别从使用的工具argv[0]

    这使得有可能有​​一个小的静态链接的可执行文件,代表多种工具,并会的基本工作原理上就任何Linux环境。

参见: https://unix.stackexchange.com/questions/315812/why-does-argv-include-the-program-name/315817

可运行的POSIX execve例子,其中argv[0] !=可执行文件的名称

其他提到的exec ,但这里是一个可运行的例子。

AC

#define _XOPEN_SOURCE 700
#include <unistd.h>

int main(void) {
    char *argv[] = {"yada yada", NULL};
    char *envp[] = {NULL};
    execve("b.out", argv, envp);
}

公元前

#include <stdio.h>

int main(int argc, char **argv) {
    puts(argv[0]);
}

然后:

gcc a.c -o a.out
gcc b.c -o b.out
./a.out

得到:

yada yada

是的, argv[0]也可以是:

  • NULL: 什么时候可以做argv [0]为空?
  • 空: 可以的argv [0]包含一个空字符串?

经测试在Ubuntu 16.10。



Answer 7:

我不知道它是否是一个几乎普遍的惯例或标准,但你应该遵守它无论哪种方式。 我从来没有见过它利用的Unix和类Unix系统之外,虽然。 在Unix环境 - 也许特别是在过去的日子 - 程序可能有显著不同的行为取决于它们调用其下的名称。

编辑:我从其他的帖子看到有人已经确定了它作为一个特定的标准来的同时,我的,但我敢肯定的惯例远远早标准。



Answer 8:

如果通过工作台的argv启动一台Amiga程序[0]不仅要通过CLI进行设置。



文章来源: Is “argv[0] = name-of-executable” an accepted standard or just a common convention?