函数main(int argc, char *argv[])中的参数argv

The parameter argv in the function main(int argc, char *argv[])

抱歉,如果这看起来像是一个基本问题。我一直在为即将到来的期中学习而学习,但我似乎无法解决这个问题。我知道 argv 可以在命令行中使用,当你需要向它发送参数时,但是 none 我的教授给我们的答案似乎是有道理的。

The parameter argv in the function main(int argc, char *argv[]) is:
A. An array of characters
B. A string
C. An array of pointers to character
D. A character pointer
E. None of the above

我感觉是上面的none,但也可能是我没有完全理解argv的概念。如有任何帮助,我们将不胜感激!

正确答案是E,上面的none。尽管参数声明看起来像指向 char 的指针数组,但 C 的规则将其调整为指向 char 的指针,C++ 的规则也是如此。

您的讲师错误地选择了选项 C,或者您的讲师为介绍性问题设计了一个不恰当的棘手问题 class,除非它是额外的学分。

我认为你的教授想要 C,即使迂腐的正确答案是 Eargv引用的数据是一个数组,但是变量本身是一个指针。我认为值得探讨为什么,因为它与数组类型或 main.

无关

考虑一个整数数组,

int a[] = { 1, 2, 3 };

这分配了 3 个相邻的整数。数组的大小是sizeof(int) * 3.

现在让我们编写一个函数来将每个成员的值加倍,

void F( int m[], size_t n ) {
    for( int i=0; i < n; i++ ) {
        m[i] *= 2;
    }

int main( int argc, char *argv[] ) {
    F(a, sizeof(a)/sizeof(a[0]));
    return EXIT_SUCCESS;
}

什么是 m?它被声明为一个数组,但它实际上是一个指针:sizeof(m) == sizeof(int*)。那是因为 C 不会将数组作为函数参数传递 。 C 中的艺术术语是数组参数 衰减 到指针。

这有点无关紧要,因为 C 语法 隐藏了许多错误,呃,差异。您可以对数组和指针使用下标表示法。出于这个原因,我们的函数 F 可以像对待数组一样对待 m almost,除了它需要长度,因为它不能从大小,因为大小是指针的大小。

让我换一种说法。调用F时,"arguments on the stack"不是a的值,即123。只有一个这样的参数,指向 a 的第一个元素的指针(通常被认为是第一个元素的地址)。您可以将该指针用作数组,部分原因是数组的名称 指的是第一个元素的地址。

现在让我们回到你的朋友argv。数组,还是指针?假设您的程序 foo 在命令行上被调用:

$ foo sam I am

操作系统是做什么的?不知何故,它必须将这 4 个字符串(字符数组)传递给您的程序。在某个地方,它必须为它们分配连续的 space。 概念上,shell 可能会做类似的事情:

char **args = calloc(5, sizeof(char*));
args[0] = "foo"; 
args[1] = "sam"; 
args[2] = "I"; 
args[3] = "am"; 

或者,

char args[5] = { "foo", "sam", "I", "am" };

无论哪种方式,它都可以将 args 传递给 execv(3),调用您的 main,并向您传递一个 ... 指针。毕竟,它不能给你传递一个数组,对吧?

请注意args必须是一个数组。如果不是 argv[1] 将毫无意义。

(当只有 4 个参数时,你问为什么有 5 个元素?有一个规则——C 或 Posix,我不记得了——数组中的最后一个元素(!)必须是 NULL 指针。)

数组还是指针?波还是粒子?你站在哪里取决于你坐在哪里。 argv 是指向 char* 的指针 a,当然。不过,根据定义,它是指向 char* 数组开头的指针。