C++ - char** argv 与 char* argv[]
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5192068/
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
C++ - char** argv vs. char* argv[]
提问by Simplicity
What is the difference between char** argv
and char* argv[]
? in int main(int argc, char** argv)
and int main(int argc, char* argv[])
?
char** argv
和 和有char* argv[]
什么区别?在int main(int argc, char** argv)
和int main(int argc, char* argv[])
?
Are they the same? Especially that the first part does not have []
.
他们是一样的吗?尤其是第一部分没有的[]
。
回答by Fred Foo
回答by James Bedford
They are indeed exactly the same.
它们确实完全相同。
The golden rule of arrays to remember is:
要记住的数组黄金法则是:
"The name of an array is a pointer to the first element of the array."
“数组的名称是指向数组第一个元素的指针。”
So if you declare the following:
因此,如果您声明以下内容:
char text[] = "A string of characters.";
char text[] = "A string of characters.";
Then the variable "text" is a pointer to the first char in the array of chars you've just declared. In other words, "text" is of type char *
. When you access an element of an array using [index], what you're actually doing is adding an offset of indexto the pointer to the first element of the array, and then dereferencing this new pointer. The following two lines will therefore initialize both variables to 't':
然后变量“text”是指向您刚刚声明的字符数组中第一个字符的指针。换句话说,“文本”的类型为char *
。当您使用 [ index]访问数组元素时,您实际所做的是将索引的偏移量添加到指向数组第一个元素的指针,然后取消引用这个新指针。因此,以下两行将两个变量初始化为“t”:
char thirdChar = text[3];
char thirdChar2 = *(text+3);
Using the square brackets is a convience provided by the language that makes the code much more readable. But the way this works is very important when you start thinking about more complex things, such as pointers to pointers. char** argv
is the same as char* argv[]
because in the second case "the name of the array is a pointerto the first element in the array".
使用方括号是语言提供的便利,使代码更具可读性。但是当您开始考虑更复杂的事情时,例如指向指针的指针,这种工作方式非常重要。char** argv
与char* argv[]
因为在第二种情况下“数组的名称是指向数组中第一个元素的指针”相同。
From this you should also be able to see why it is that array indexes start from 0. The pointer to the first element is the array's variable name (golden rule again) plus an offset of... nothing!
从这里你也应该能够看到为什么数组索引从 0 开始。指向第一个元素的指针是数组的变量名(又是黄金法则)加上偏移量……什么都没有!
I've had debates with a friend of mine as to which is better to use here. With the char* argv[]
notation it may be clearer to the reader that this is in fact an "array of pointers to characters" as opposed to the char** argv
notation which can be read as a "pointer to a pointer to a character". My opinion is that this latter notation doesn't convey as much information to the reader.
我和我的一个朋友争论过这里用哪个更好。有了char* argv[]
符号,读者可能更清楚,这实际上是一个“指向字符的指针数组”,而不是char** argv
可以被理解为“指向字符指针的指针”的符号。我的观点是,后一种符号并没有向读者传达那么多信息。
It's good to know that they're exactly the same, but for readablity I think that if the intention is an array of pointers then the char* argv[]
notation conveys this much more clearly.
很高兴知道它们完全相同,但为了可读性,我认为如果意图是一个指针数组,那么char* argv[]
符号会更清楚地传达这一点。
回答by Erik
For all practical purposes, they're the same. This is due to C/C++'s handling of arrays passed as arguments, where an array decays to a pointer.
出于所有实际目的,它们是相同的。这是由于 C/C++ 处理作为参数传递的数组,其中数组衰减为指针。
回答by David Cournapeau
For the first part of the question:
对于问题的第一部分:
- char** argv: pointer to a pointer to a char
- char* argv[]: pointer to an array
- char** argv:指向字符指针的指针
- char* argv[]: 指向数组的指针
So the question is whether a pointer to a type C and an array C[] are the same things. They are not at all in general, BUT they are equivalent when used in signatures.
所以问题是指向类型 C 的指针和数组 C[] 是否相同。它们根本不是一般性的,但是在用于 signatures 时它们是等效的。
In other words, there is no difference in your example, but it is important to keep in mind the difference between pointer and array otherwise.
换句话说,您的示例没有区别,但重要的是要记住指针和数组之间的区别。
回答by Jake
The bracket form is only useful in statement declarations like:
括号形式仅在语句声明中有用,例如:
char *a[] = {"foo", "bar", "baz"};
printf("%d\n", sizeof a / sizeof *a);
// prints 3
Because it knows at compile time the size of the array. When you pass a bracket form as parameter to a function (main or some other one), the compiler has no idea what the size of the array would be at runtime, so it is exactly the same as char **a. I prefer char **argv since it's clearer that sizeof wouldn't work like it would on the statement declaration form.
因为它在编译时就知道数组的大小。当您将括号形式作为参数传递给函数(main 或其他函数)时,编译器不知道运行时数组的大小,因此它与 char **a 完全相同。我更喜欢 char **argv ,因为更清楚的是 sizeof 不会像在声明声明表上那样工作。
回答by yanpas
There is a difference between TYPE * NAME
and TYPE NAME[]
in both C and C++. In C++ both types are not interchagneable. For example following function is illegal (you will get an error) in C++, but legal in C (you will get warning):
之间存在差异TYPE * NAME
和TYPE NAME[]
在C和C ++。在 C++ 中,这两种类型都不可互换。例如以下函数在 C++ 中是非法的(你会得到一个错误),但在 C 中是合法的(你会得到警告):
int some (int *a[3]) // a is array of dimension 3 of pointers to int
{
return sizeof a;
}
int main ()
{
int x[3][3];
std::cout << some(x)<< std::endl;
return 0;
}
To make it legal just change signature to int some (int (*a)[3])
(pointer to array of 3 ints) or int some (int a[][3])
. The number in last square brackets must be equal to an argument's. Converting from array of arrays to an array of pointers is illegal. Converting from pointer to pointer to array of arrays is illegal too. But converting pointer to pointer to an array of pointers is legal!
要使其合法,只需将签名更改为int some (int (*a)[3])
(指向 3 个整数数组的指针)或int some (int a[][3])
. 最后方括号中的数字必须等于参数的。从数组数组转换为指针数组是非法的。从指针转换为指向数组数组的指针也是非法的。但是将指针转换为指向指针数组的指针是合法的!
So remember: Only nearest to dereference type signature doesn't matter, others do(in the context of pointers and arrays, sure).
所以请记住:只有最接近取消引用的类型签名无关紧要,其他人则如此(当然,在指针和数组的上下文中)。
Consider we have a as pointer to pointer to int:
考虑我们有一个指向 int 的指针:
int ** a;
&a -> a -> *a -> **a
(1) (2) (3) (4)
- You cannot change this value, the type is
int ***
. May be taken by function asint **b[]
orint ***b
. The best isint *** const b
. - The type is
int **
. May be taken by function asint *b[]
orint ** b
. Brackets of the array declaratin may be leaved empty or contain any number. - The type is
int *
. May be taken by function asint b[]
orint * b
or evenvoid * b
- Should be taken as int parameter. I don't want to fall into details, like implicit constructor call.
- 您不能更改此值,类型为
int ***
。可以被函数视为int **b[]
或int ***b
。最好的是int *** const b
。 - 类型是
int **
。可以被函数视为int *b[]
或int ** b
。数组 declaratin 的括号可以留空或包含任何数字。 - 类型是
int *
。可以采取的功能int b[]
或者int * b
甚至void * b
- 应作为 int 参数。我不想陷入细节,比如隐式构造函数调用。
Answeringyour question: the real type of argumets in main functionis char ** argv
, so it may be easily represented as char *argv[]
(but not as char (*argv)[]
). Also argv
name of main function may be safelychanged.
You may check it easily: std::cout << typeid(argv).name();
(PPc = pointer to p. to char)
回答您的问题:main 函数中参数的真正类型是char ** argv
,因此它可以很容易地表示为char *argv[]
(但不能表示为char (*argv)[]
)。也argv
可以安全地更改主函数的名称。您可以轻松检查它:std::cout << typeid(argv).name();
(PPc = 指向 p. 到 char 的指针)
By the way: there is a cool feature, passing arrays as references:
顺便说一句:有一个很酷的功能,将数组作为引用传递:
void somef(int (&arr)[3])
{
printf("%i", (sizeof arr)/(sizeof(int))); // will print 3!
}
Moreoverpointer to anything may be implicitly accepted (converted) by function as void pointer. But only single pointer (not pointer to pointer etc.).
此外,指向任何东西的指针都可以作为 void 指针被函数隐式接受(转换)。但只有单个指针(不是指向指针等的指针)。
Further reading:
进一步阅读:
- Bjarne Stroustrup, C++, chapter 7.4
- C pointers FAQ
- Bjarne Stroustrup,C++,第 7.4 章
- C 指针常见问题
回答by user5858
Both are same for your usage except for the following subtle differences:
除了以下细微差别外,两者的用法相同:
- Sizeof will give different results for both
- Also second one may not be reassigned to new memory area since it's an array
- With second one you can use only those indexes which are valid. It's unspecified by C/C++ if you try to use an array index beyond array length. However with char** you can use any index from 0 to ...
- Second form can only be used as formal parameters to a function. While first can even be used to declare variables within a stack.
- Sizeof 将为两者提供不同的结果
- 另外第二个可能不会重新分配给新的内存区域,因为它是一个数组
- 对于第二个,您只能使用那些有效的索引。如果您尝试使用超出数组长度的数组索引,则 C/C++ 未指定它。但是,对于 char**,您可以使用从 0 到 ...
- 第二种形式只能用作函数的形式参数。虽然 first 甚至可以用于在堆栈中声明变量。