C语言 对于 main() 的第二个参数,char *argv[] 和 char **argv 之间的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27213580/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Difference between char *argv[] and char **argv for the second argument to main()
提问by Jhansi Rani
CODE 1
代码 1
#include<stdio.h>
int main(int argc, char *argv[])
{
int j;
printf("%d", argv[1][0]);
return 0;
}
CODE 2
代码 2
#include<stdio.h>
int main(int argc, char **argv)
{
int j;
printf("%d", argv[1][0]);
return 0;
}
CODE 1 and CODE 2both give same output. but argument 2of main function in CODE 1 and CODE 2 are different. Array of pointers are created above data section at compile time. argv is array of pointers. Then we should declare argument in main function as pointer to pointer to character i.e., **argv. How it is correct to declare as in CODE 1?
CODE 1 和 CODE 2都给出相同的输出。但是CODE 1 和 CODE 2 中 main 函数的参数 2是不同的。指针数组是在编译时在数据部分上方创建的。argv 是指针数组。然后我们应该在 main 函数中声明参数为指向字符指针的指针,即 **argv。在 CODE 1 中声明如何正确?
回答by bmargulies
It is fundamental to c that char** xand char* x[]are two ways of expressing the same thing. Both declare that the parameter receives a pointer to an array of pointers. Recall that you can always write:
是 c 的基础,char** x和char* x[]是表达同一事物的两种方式。两者都声明参数接收一个指向指针数组的指针。回想一下,你总是可以写:
char *parray[100];
char **x;
x = &parray[0];
and then use x identically.
然后同样使用 x 。
回答by nishantbhardwaj2002
Basically, char* argv[] means array of char pointers, whereas char** argv means pointer to a char pointer.
基本上, char* argv[] 表示 char 指针数组,而 char** argv 表示指向 char 指针的指针。
In any array, the name of the array is a pointer to first element of the array, that is, it contains the address of the first element.
在任何数组中,数组名都是指向数组第一个元素的指针,即包含第一个元素的地址。
So in the code given below, in char array x, x is a pointer to first element, '1', which is a character. So it's pointer to a character.
所以在下面给出的代码中,在字符数组 x 中,x 是指向第一个元素 '1' 的指针,它是一个字符。所以它是指向一个字符的指针。
And in array arr, arr is pointer first element, x, which is itself a pointer to a character. So it a pointer to another pointer.
在数组 arr 中,arr 是指针第一个元素 x,它本身就是一个指向字符的指针。所以它是一个指向另一个指针的指针。
Hence, x is char*, and arr is char**.
因此,x 是 char*,而 arr 是 char**。
While receiving something in a function, basic rule is that, you have to tell the type of the thing you are receiving. So either you simply say that you want to receive a char**, or you can also say char* arr[].
在函数中接收东西时,基本规则是,你必须告诉你正在接收的东西的类型。所以要么你简单地说你想要接收一个 char**,要么你也可以说 char* arr[]。
In first case, we don't need to think anything complex. We simply know, we are receiving an array of char*. Don't we know this? So, we receive it, and use it.
在第一种情况下,我们不需要考虑任何复杂的事情。我们只知道,我们正在接收一个 char* 数组。我们不知道这个吗?所以,我们接收它,并使用它。
In second case, it is simple, as i have explained above that arr is a char**, you can put this as it's type and receive it safely. Now the system knows the type of the stuff we have received, we can access next elements by simply using array annotation. It's like, we have received the starting address of the array, we can surely go to the next elements, and as we know it's type, we know what it contains and how we can use that further. We know it contains pointer to char, so we can legally access them as well.
在第二种情况下,它很简单,正如我上面解释的 arr 是一个字符**,你可以把它作为它的类型并安全地接收它。现在系统知道我们收到的东西的类型,我们可以通过简单地使用数组注释来访问下一个元素。就好像,我们已经收到了数组的起始地址,我们肯定可以转到下一个元素,因为我们知道它的类型,我们知道它包含什么以及我们如何进一步使用它。我们知道它包含指向 char 的指针,因此我们也可以合法地访问它们。
void func1(char* arr[])
{
//function body
}
void func2(char** arr)
{
//function body
}
int main()
{
//x, y and z are pointer to char
char x[3]={'1', '2', '3'};
char y[3]={'4', '5', '6'};
char z[3]={'7', '8', '9'};
//arr is pointer to char pointer
char* arr[3]={x, y, z};
func1(arr);
func2(arr);
}
回答by nishantbhardwaj2002
They're exactly the same. §5.1.2.2.2 of the C11 standard states:
他们完全一样。C11 标准的 §5.1.2.2.2 规定:
The function called at program startup is named
main. The implementation declares no prototype for this function. It shall be defined with a return type ofintand with no parameters:int main(void) { /* ... */ }or with two parameters (referred to here as
argcandargv, though any names may be used, as they are local to the function in which they are declared):int main(int argc, char *argv[]) { /* ... */ }or equivalent;10)or in some other implementation-defined manner.
10) Thus,
intcan be replaced by a typedef name defined asint, or the type ofargvcan be written aschar ** argv, and so on.
程序启动时调用的函数名为
main. 实现声明没有此函数的原型。它应定义为返回类型int并且不带参数:int main(void) { /* ... */ }或带有两个参数(这里称为
argcandargv,尽管可以使用任何名称,因为它们对于声明它们的函数是本地的):int main(int argc, char *argv[]) { /* ... */ }或同等学历; 10)或以其他一些实现定义的方式。
10) 因此,
int可以替换为定义为 的 typedef 名称int,或者argv可以将的类型写为char ** argv,依此类推。
Clearly the intent is for both declarations to be identical. On top of that, the rule is described in §6.7.6.3/7:
显然,目的是使两个声明相同。最重要的是,该规则在 §6.7.6.3/7 中有描述:
A declaration of a parameter as ‘‘array of type'' shall be adjusted to ‘‘qualified pointer to type'', where the type qualifiers (if any) are those specified within the
[and]of the array type derivation. ...
将参数声明为“类型数组”应调整为“指向类型”的限定指针 ,其中类型限定符(如果有)是在数组类型派生的
[和]中指定的那些。...
回答by jde-chil
declaring an array like this
像这样声明一个数组
char array[]
makes it const which means that you CAN'T have the following code
使它成为 const 这意味着你不能有以下代码
char array[] = "hello";
array = "hey";
even though the second string is smaller and should fit you get this error
即使第二个字符串较小并且应该适合您也会收到此错误
error: array type 'char [6]' is not assignable
错误:数组类型“char [6]”不可分配
if you have **argvyou can write
如果你有**argv你可以写
main(int argc, char **argv)
{
char **other_array;
/*
* do stuff with other_array
*/
argv = other_array;
}
if you have *argv[]then
如果你有*argv[]那么
main(int argc, char *argv[])
{
char **other_array;
/*
* do stuff with other_array
*/
argv = other_array;
}
gives you this warning
给你这个警告
warning: assigning to 'const char **' from 'char **' discards qualifiers in nested pointer types
警告:从 'char **' 分配给 'const char **' 会丢弃嵌套指针类型中的限定符
so it is technically a small optimisation as if you had written const
所以这在技术上是一个小的优化,就像你写的一样 const

