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

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

它说,

程序将命令行字符串存储在内存中,并将每个字符串的地址存储在指针数组中。 该数组的地址存储在第二个参数中。 按照惯例,指向指针的指针称为argv ,用于参数值。

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

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

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

[…]如果argc的值大于零, 则数组成员argv[0]argv[argc-1]包含指向字符串的指针 ,[…]

[…]和argv数组指向的字符串[…]

所以,基本上, argv是一个指向字符串数组的第一个元素的指针。 从替代forms可以更清楚地看出这一点,

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

你可以将它改为指向指向以null结尾的char数组的第一个元素的指针数组的第一个元素的指针,但我更喜欢坚持使用字符串。


注意:

在上面的答案中阐明“指向数组第一个元素的指针”的用法,遵循§6.3.2.1/ p3

除非它是sizeof运算符, _Alignof运算符或一元&运算符的操作数,或者是用于初始化数组的字符串文字,否则具有类型”数组类型”的表达式将转换为表达式输入”指向类型‘的指针 ,指向数组对象的初始元素,而不是左值。 […]

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

                  一些
                  排列

                  + ------- + + ------ + ------ + ------------- + ------ +
 argv ----------> |  |  |  |  |  |  |
                  |  0x100 + ------> |  |  |  。  。  。  。  。  。  |  | 程序名称1
          0x900 |  |  |  |  |  |  |
                  |  |  + ------ + ------ + ------------- + ------ +
                  + ------- + 0x100 0x101
                  |  |  + ------ + ------ + ------------- + ------ +
                  |  0x205 |  |  |  |  |  |
          0x904 |  + ------> |  |  |  。  。  。  。  。  。  |  |  Arg 1
                  |  |  。  |  |  |  |  |
                  + ------- + + ------ + ------ + ------------- + ------ +
                  |  。  |  。  0x205 0x206
                  |  。  |
                  |  。  |  。
                  |  。  |
                  + ------- +。  + ------ + ------ + ------------- + ------ +
                  |  |  |  |  |  |  |
                  |  0x501 + ------> |  |  |  。  。  。  。  。  。  |  |  Arg argc-1
                  |  |  |  |  |  |  |
                  + ------- + + ------ + ------ + ------------- + ------ +
                  |  |  0x501 0x502
                  |  NULL |
                  |  |
                  + ------- +


 0xXXX表示内存地址


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

这个线程是这样的火车残骸。 情况如下:

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

有时候人们会写“指向X数组的指针”来表示“指向X数组的第一个元素的指针”。 你必须使用上下文和类型来确定它们是否确实意味着它。

对,就是这样。

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

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

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

以下代码显示argv的值, argv的内容,并在argv内容指向的内存上执行内存转储。 希望这能说明间接的意义。

 #include  #include  print_memory(char * print_me) { char * p; for (p = print_me; *p != '\0'; ++p) { printf ("%p: %c\n", p, *p); } // Print the '\0' 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是指针......指向字符的指针

是。

argv的类型是char** ,即指向char指针。 基本上,如果您将char*视为字符串,则argv是指向字符串数组的指针。