[英]C++ - char** argv vs. char* argv[]
What is the difference between char** argv
and char* argv[]
? char** argv
和char* argv[]
什么区别? in int main(int argc, char** argv)
and int main(int argc, 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 []
.特别是第一部分没有[]
。
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.";
Then the variable "text" is a pointer to the first char in the array of chars you've just declared. 然后变量“text”是指向你刚刚声明的字符数组中第一个字符的指针。 In other words, "text" is of type char *
. 换句话说,“text”的类型为char *
。 When you access an element of an array using [ index ], what you're actually doing is adding an offset of index to the pointer to the first element of the array, and then dereferencing this new pointer. 当您使用[ index ]访问数组的元素时,您实际在做的是将索引的偏移量添加到指向数组的第一个元素的指针,然后取消引用此新指针。 The following two lines will therefore initialize both variables to 't': 因此,以下两行将两个变量初始化为'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 pointer to 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". 使用char* argv[]
符号,读者可能会更清楚这实际上是一个“指向字符的指针数组”而不是char** argv
符号,它可以被读作“指向指针的指针”字符”。 My opinion is that this latter notation doesn't convey as much information to the reader. 我的观点是,后一种符号并没有向读者传达那么多信息。
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[]
表示法会更清楚地传达这一点。
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 ++处理作为参数传递的数组,其中数组衰减为指针。
For the first part of the question: 对于问题的第一部分:
So the question is whether a pointer to a type C and an array C[] are the same things. 所以问题是指向类型C和数组C []的指针是否相同。 They are not at all in general, BUT they are equivalent when used in 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. 换句话说,您的示例没有区别,但重要的是要记住指针和数组之间的区别。
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. 将括号形式作为参数传递给函数(main或其他函数)时,编译器不知道数组在运行时的大小,因此它与char ** a完全相同。 I prefer char **argv since it's clearer that sizeof wouldn't work like it would on the statement declaration form. 我更喜欢char ** argv,因为更清楚的是sizeof不会像声明声明表单那样工作。
This is a simple example I came up with, which have two functions (Main_1, Main_2) take the same arguments as the main function.这是我想出的一个简单示例,其中有两个函数(Main_1、Main_2)采用与主函数相同的参数。
I hope this clear things up..我希望这能解决问题..
#include <iostream>
void Main_1(int argc, char **argv)
{
for (int i = 0; i < argc; i++)
{
std::cout << *(argv + i) << std::endl;
}
}
void Main_2(int argc, char *argv[])
{
for (int i = 0; i < argc; i++)
{
std::cout << *(argv + i) << std::endl;
}
}
int main()
{
// character arrays with null terminators (0 or '\o')
char arg1[] = {'h', 'e', 'l', 'l', 'o', 0};
char arg2[] = {'h', 'o', 'w', 0};
char arg3[] = {'a', 'r', 'e', '\0'};
char arg4[] = {'y', 'o', 'u', '\n', '\0'};
// arguments count
int argc = 4;
// array of char pointers (point to each character array (arg1, arg2, arg3 and arg4)
char *argPtrs[] = {arg1, arg2, arg3, arg4};
// pointer to char pointer array (argPtrs)
char **argv = argPtrs;
Main_1(argc, argv);
Main_2(argc, argv);
// or
Main_1(argc, argPtrs);
Main_2(argc, argPtrs);
return 0;
}
Output :输出 :
hello
how
are
you
hello
how
are
you
hello
how
are
you
hello
how
are
you
There is a difference between TYPE * NAME
and TYPE NAME[]
in both C and C++. C和C ++中的TYPE * NAME
和TYPE NAME[]
之间存在差异。 In C++ both types are not interchagneable. 在C ++中,这两种类型都不可交叉。 For example following function is illegal (you will get an error) in C++, but legal in C (you will get warning): 例如,以下函数在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])
. 为了使其合法,只需将签名更改为int some (int (*a)[3])
(指向3个int的数组)或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! 但是将指针转换为指向指针数组的指针是合法的!
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: 考虑我们有一个as指针指向int:
int ** a;
&a -> a -> *a -> **a
(1) (2) (3) (4)
int ***
. 你不能改变这个值,类型是int ***
。 May be taken by function as int **b[]
or int ***b
. 可以通过函数作为int **b[]
或int ***b
。 The best is int *** const b
. 最好的是int *** const b
。 int **
. 类型是int **
。 May be taken by function as int *b[]
or int ** b
. 函数可以作为int *b[]
或int ** b
。 Brackets of the array declaratin may be leaved empty or contain any number. 阵列声明的括号可以留空或包含任何数字。 int *
. 类型是int *
。 May be taken by function as int b[]
or int * b
or even void * b
函数可以作为int b[]
或int * b
甚至void * b
Answering your question: the real type of argumets in main function is char ** argv
, so it may be easily represented as char *argv[]
(but not as char (*argv)[]
). 回答你的问题: main函数中真正的争论类型是char ** argv
,因此它可以很容易地表示为char *argv[]
(但不能表示为char (*argv)[]
)。 Also argv
name of main function may be safely changed. 也可以安全地更改主要功能的argv
名称。 You may check it easily: std::cout << typeid(argv).name();
您可以轻松检查它: std::cout << typeid(argv).name();
(PPc = pointer to p. to char) (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!
}
Moreover pointer to anything may be implicitly accepted (converted) by function as void pointer. 此外,指向任何事物的指针可能被函数隐式接受(转换)为void指针。 But only single pointer (not pointer to pointer etc.). 但只有单个指针(不是指针指针等)。
Further reading: 进一步阅读:
Both are same for your usage except for the following subtle differences: 两者的用法相同,但以下细微差别除外:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.