C 中命令行参数 `argv` 的类型是什么?

What is the type of command-line argument `argv` in C?

我正在阅读 C Primer Plus 中关于命令行参数的部分 argv,但我很难理解这句话。

它说,

The program stores the command line strings in memory and stores the address of each string in an array of pointers. The address of this array is stored in the second argument. By convention, this pointer to pointers is called argv, for argument values .

这是否意味着命令行字符串作为指向 char 数组的指针数组存储在内存中?

是的,完全正确。

argv 是一个 char**char*[],或者只是一个 char* 指针数组。

所以 argv[0] 是一个 char*(字符串),argv[0][0] 是一个 char

是的。

argv的类型是char**,即指向char的指针。基本上,如果你认为 char* 是一个字符串,那么 argv 就是一个指向字符串数组的指针。

直接引用C11,章节§5.1.2.2.1/p2,程序启动,(强调我的)

int main(int argc, char *argv[]) { /* ... */ }

[...] If the value of argc is greater than zero, the array members argv[0] through argv[argc-1] inclusive shall contain pointers to strings, [...]

[...] and the strings pointed to by the argv array [...]

所以,基本上,argv 是指向字符串数组第一个元素的指针 注意。这可以从 替代形式 ,

中更清楚

int main(int argc, char **argv) { /* ... */ }

您可以将其改写为指向空终止 char 数组的第一个元素的指针数组的第一个元素的指针,但我更愿意坚持使用 strings 。


注意:

为了阐明上述答案中 "pointer to the first element of an array" 的用法,请遵循 §6.3.2.1/p3

Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. [...]

argvchar ** 类型。 它不是数组。它是指向 char 的指针。命令行参数存储在内存中,每个内存位置的地址存储在一个数组中。这个数组是指向 char 的指针数组。 argv 指向这个数组的第一个元素。

                  Some
                  array

                 +-------+        +------+------+-------------+------+
argv ----------> |       |        |      |      |             |      |
                 | 0x100 +------> |      |      | . . . . . . |      |  Program Name1
         0x900   |       |        |      |      |             |      |
                 |       |        +------+------+-------------+------+
                 +-------+         0x100  0x101
                 |       |        +------+------+-------------+------+
                 | 0x205 |        |      |      |             |      |
         0x904   |       +------> |      |      | . . . . . . |      |  Arg1
                 |       |  .     |      |      |             |      |
                 +-------+        +------+------+-------------+------+
                 |  .    |  .      0x205  0x206
                 |  .    |
                 |  .    |  .
                 |  .    |
                 +-------+  .     +------+------+-------------+------+
                 |       |        |      |      |             |      |
                 | 0x501 +------> |      |      | . . . . . . |      |  Argargc-1
                 |       |        |      |      |             |      |
                 +-------+        +------+------+-------------+------+
                 |       |         0x501  0x502
                 | NULL  |
                 |       |
                 +-------+


0xXXX Represents memory address


1.在大多数情况下,argv[0] 表示程序名称,但如果程序名称在主机环境中不可用,则 argv[0][0] 表示空字符。

这个帖子真是一团糟。情况是这样的:

  • 有一个数组包含 argc+1 个类型为 char * 的元素。
  • argv 指向该数组的第一个元素。
  • 还有 argc 个其他类型 char 和不同长度的数组,包含表示命令行参数的空终止字符串。
  • 指针数组的每个元素都指向char数组之一的第一个字符;除了指针数组的最后一个元素,它是一个空指针。

有时人们写 "pointer to array of X" 的意思是 "pointer to the first element of an array of X"。您必须使用上下文和类型来确定它们是否真的意味着那个。

argv 是指向字符的指针数组。

以下代码显示argv的值、argv的内容,并对argv的内容指向的内存执行内存转储。希望这能阐明间接的含义。

#include <stdio.h>
#include <stdarg.h>

print_memory(char * print_me)
{
    char * p;
    for (p = print_me; *p != '[=10=]'; ++p)
    {
        printf ("%p: %c\n", p, *p);
    }

    // Print the '[=10=]' for good measure
    printf ("%p: %c\n", p, *p);

}

int main (int argc, char ** argv) {
    int i;

    // Print argv
    printf ("argv: %p\n", argv);
    printf ("\n");

    // Print the values of argv
    for (i = 0; i < argc; ++i)
    {
        printf ("argv[%d]: %p\n", i, argv[i]);
    }
    // Print the NULL for good measure
    printf ("argv[%d]: %p\n", i, argv[i]);
    printf ("\n");

    // Print the values of the memory pointed at by argv
    for (i = 0; i < argc; ++i)
    {
        print_memory(argv[i]);
    }

    return 0;
}

样本运行:

$ ./a.out Hello World!
argv: ffbfefd4

argv[0]: ffbff12c
argv[1]: ffbff134
argv[2]: ffbff13a
argv[3]: 0

ffbff12c: .
ffbff12d: /
ffbff12e: a
ffbff12f: .
ffbff130: o
ffbff131: u
ffbff132: t
ffbff133:
ffbff134: H
ffbff135: e
ffbff136: l
ffbff137: l
ffbff138: o
ffbff139:
ffbff13a: W
ffbff13b: o
ffbff13c: r
ffbff13d: l
ffbff13e: d
ffbff13f: !
ffbff140:

$

你有一个从 ffbff12cffbff140 的大连续数组,其中包含命令行参数(标准不保证这是连续的,但通常是这样做的) . argv 只包含指向该数组的指针,因此您知道在哪里查找单词。

argv 是一个指针……指向指针……指向字符