我应该在C中使用char ** argv或char * argv 吗?

我只是在学习C,并想知道在我的主要方法中应该使用哪一个。 有什么区别吗?

编辑:那么哪一个更常用?

正如你刚刚学习C,我build议你真正尝试理解数组和指针之间的区别 ,而不是普通的东西。

在参数和数组领域,有一些令人困惑的规则在继续之前应该清楚。 首先, 你在参数列表中声明的内容是特殊的。 有这种情况下,作为C中的函数参数是没有意义的

  • 函数作为参数
  • 数组作为参数

数组作为参数

第二个也许不是很清楚。 但是,当你认为数组维数的大小是C中types的一部分(以及未给出维数大小的数组具有不完整types)时,就会变得很清楚。 所以,如果你要创build一个按值接受数组的函数(接收一个副本),那么它只能为一个尺寸这么做! 另外,数组可以变大,C尽可能快。

在C中,由于这些原因, 数组值不存在。 如果你想获得一个数组的值,你得到的是一个指向该数组的第一个元素的指针。 而实际上这已经是解决scheme了。 C编译器会将相应参数的types转换为指针,而不是预先绘制数组参数无效。 记住这一点,这是非常重要的。 该参数不是一个数组,而是一个指向相应元素types的指针。

现在,如果您尝试传递数组,则传递的是指向数组的第一个元素的指针。

游览:function作为参数

为了完成,因为我认为这会帮助你更好地理解这个问题,让我们来看看当你试图以一个函数作为参数时,事情的状态是什么。 事实上,首先它是没有任何意义的。 一个参数怎么可能是一个函数? 呃,我们当然要在那个地方有一个variables! 所以编译器在发生这种情况时再次将函数转换为函数指针 。 尝试传递一个函数会传递一个指向相应函数的指针。 所以,以下是相同的(类似于数组的例子):

 void f(void g(void)); void f(void (*g)(void)); 

请注意, *g周围的括号是必需的。 否则,它将指定一个返回void*的函数,而不是指向返回void的函数的指针。

回到数组

现在,我刚开始说数组可以有一个不完整的types – 如果你还没有给出一个大小的话,会发生这种情况。 由于我们已经知道一个数组参数不存在,而是任何数组参数都是一个指针,所以数组的大小并不重要。 这意味着,编译器将翻译所有以下内容,并且都是相同的事情:

 int main(int c, char **argv); int main(int c, char *argv[]); int main(int c, char *argv[1]); int main(int c, char *argv[42]); 

当然,放入任何尺寸都没有什么意义,只是被扔掉了。 出于这个原因,C99为这些数字提出了新的含义,并允许在括号之间出现其他内容:

 // says: argv is a non-null pointer pointing to at least 5 char*'s // allows CPU to pre-load some memory. int main(int c, char *argv[static 5]); // says: argv is a constant pointer pointing to a char* int main(int c, char *argv[const]); // says the same as the previous one int main(int c, char ** const argv); 

最后两行说你不能在函数内改变“argv” – 它已经成为一个常量指针。 尽pipe只有less数C编译器支持那些C99function。 但是这些特征清楚地表明“arrays”实际上不是一个。 这是一个指针。

一个警告的话

请注意,我上面所说的只有当你有一个数组作为一个函数的参数是真实的。 如果你使用本地数组,一个数组不会是一个指针。 它将像一个指针一样工作,因为正如前面所解释的那样,一个数组在被读取的时候会被转换为一个指针。 但是不要把它与指针混淆起来。

一个典型的例子如下:

 char c[10]; char **c = &c; // does not work. typedef char array[10]; array *pc = &c; // *does* work. // same without typedef. Parens needed, because [...] has // higher precedence than '*'. Analogous to the function example above. char (*array)[10] = &c; 

你可以使用,这取决于你想如何使用它。 char* argv[] (大部分)等同于char ** argv 这两种forms都是指向char的指针,唯一的区别是用char *argv[]你告诉编译器argv的值不会改变(尽pipe它指向的值仍然可以)。 其实我错了,他们完全相同。 看到莱特的评论和他的回答 。

这真的取决于你想如何使用它(你可以在任何情况下使用):

 // echo-with-pointer-arithmetic.c #include <stdio.h> int main(int argc, char **argv) { while (--argc > 0) { printf("%s ", *++argv); } printf("\n"); return 0; } // echo-without-pointer-arithmetic.c #include <stdio.h> int main(int argc, char *argv[]) { int i; for (i=1; i<argc; i++) { printf("%s ", argv[i]); } printf("\n"); return 0; } 

至于哪一个更常见 – 没关系。 任何经验丰富的C程序员阅读你的代码将看到两者可以互换(在正确的条件下)。 就像一个经验丰富的英语读者一样轻松地读“他们是”和“他们”。

更重要的是,你学习阅读并认识到他们有多相似。 你会阅读比你写的更多的代码,而且你需要同时使用这两种代码。

您可以使用两种forms中的任何一种,如C数组和指针在函数参数列表中可互换。 请参阅http://en.wikipedia.org/wiki/C_(programming_language)#Array-pointer_interchangeability

它没有什么区别,但我使用char *argv[]因为它显示的是一个固定大小的可变长度string数组(通常是char * )。

它并没有真正有所作为,但后者更具可读性。 你给出的是一个char指针数组,就像第二个版本所说的那样。 但是,它可以隐式转换为像第一个版本中的双字符指针。

char **→指向字符指针的字符和char * argv []表示字符指针的数组。 因为我们可以使用指针而不是数组,所以都可以使用。

你应该把它声明为char *argv[] ,因为有许多等价的声明方法,最接近它的直观含义:一串string。

我没有看到使用任何一种方法而不使用其他方法的特殊优点 – 使用最符合其他代码的约定。

如果你需要不同的或dynamic的string,char **可能会更容易处理。 如果你的string数量是固定的,char * var []将是首选。

我知道这已经过时了,但是如果你只是在学习C语言,而不做任何重大的事情,不要使用命令行选项。

如果您不使用命令行参数,请不要使用任何一个。 只需将main函数声明为int main()

  • 希望程序的用户能够将文件拖放到您的程序中,以便您可以使用它或者更改程序的结果
  • 想要处理命令行选项( -help/?或terminal或命令提示符中的program name之后的任何其他内容)

使用哪一个对你更有意义。 否则,只要使用int main()毕竟,如果你最终想要添加命令行选项,你可以在以后轻松编辑它们。