双重指针和指针数组之间的区别

17
在一般的C/C++程序中,我们通常将主函数写成以下两种形式之一。
int main(int c, char **argv)
或者
int main(int c, char *argv[])

这里的 argv 表示指针数组,但我们甚至可以用 ** 表示双重指针(指向指针的指针)。

例如:

char p,*q,**r;
q=&p;
r=&q;

这里的 r 是一个双指针而不是指针数组。

有人能解释一下区别吗?


我在这里找到了答案 1. 第一个答案 2. 第二个答案 - user4909217
“double pointer” 在 C 或 C++ 中并不存在。你在这里使用的是“指向指针”的指针。 - mlp
3个回答

11

当用作函数参数时

char a[]  // compiler interpret it as pointer to char

等同于

char *a

同样地,在 main 函数的声明中,char *argv[]char **argv 是等价的。需要注意的是,在这两种情况下,argv 的类型均为 char **(而不是指针数组!)。

但对于其他声明来说并非如此。

char **r;
char *a[10];
在这种情况下,r 是指向指针的指针类型,指向char,而 a 是指向char指针的数组类型。
该赋值。
r = a;   // equivalent to r = &a[0] => r = &*(a + 0) => r = a

因为在这个表达式中,数组类型 a 再次被转换为指向其第一个元素的指针,因此为 char ** 类型。

始终记住,数组和指针是两种不同的类型。指针和数组的等价性意味着指针算术和数组索引是等效的。

建议阅读:


2

argv是一个参数,因此数组会衰减为指针,除了大小(int c)之外没有其他方式可以区分。

当双指针和指针数组不是参数时,它们的语法有时看起来相似,但它们的类型是不同的,因此编译器为两者生成不同类型的代码。

当感兴趣的变量不是函数参数时,sizeof将为指向指针和指针数组的不同大小提供不同的大小。

稍微相关的问题:extern声明,T* v/s T[]


@mrtimdog 感谢您的评论。我邀请您编辑答案或指出需要编辑的地方。 - Mohit Jain

1

看! 双指针实际上是这样存储的
假设

int p,*q,**r; 
p=50;

假设p的地址为400(&p400),如果我们写q=p并打印q,我们将得到400作为答案,因为q指向p的地址,而*p将呈现50作为输出,因为operator *指的是“地址上的值”。 现在,假设q的地址为500(&q输出500),因此当我们这样做时:r=qr包含值500,并在前缀r**r时,输出应该是400,因为r呈现存储p的地址的q的值,它是一个指针变量。

因此,如果在C程序中运行以下代码

int main()
{
   int p,*q,**r; //assume the address of p to be 400
                 //assume the address of q to be 500
   p=50;
   q=p;
   r=q;

printf("Value of p-->%d",p);
printf("\nValue of q-->%d",q);
printf("\nValue at address of q \"in the address displayed above\"-->%d",*p);
printf("\nValue of r \"which will be the address of q\"-->%d",r);
printf("\nValue of r \"which will be the adddress of p-->%d",*r);
printf("\nValue of r \"which will be the value of p\"-->%d",**r);
/*
Please change the format specifiers and replace the specifier from %d to %u in case the address value is not being displayed
*/
return 0;
}

输出
-------
p的值--> 50
q的值--> 400
在上面显示的地址中q的值--> 50
r的值 "将是q的地址"--> 500
r的值 "将是p的地址"--> 400
r的值 "将是p的值"--> 50
通过上面的例子,我试图解释双指针的用法。也许你已经知道了,但我还是想生动地阐述一下。
现在结合数组来使用上面的例子。 看看吧,数组已经是指针了,因为它们可以被引用为*(a+1)或a[1]。 因此,双指针可能意味着指针数组或字符串数组,具体取决于您的问题。双指针符号的使用取决于情况。
在您发布的问题中,_TCHAR**argv或简单地说char **argv是控制台输入的字符数组,它总是被接受为字符流。
在Java中,我们使用类似的东西,例如public static void main(String argv[])。这清楚地表明主方法接受的输入是字符数组(或字符串,以便更加通用)的数组。
希望您已经理解了区别。如果没有,请评论。我会给您解释的。
谢谢。

这篇文章存在格式问题,即用于指针的星号(*)被解释为斜体或加粗的 Markdown。你的第一段完全是加粗的。请编辑你的帖子并修复错误。最简单的方法可能是将所有指针包装在代码格式化(ctrl-k)中,以便在代码块内禁用斜体和加粗。 - Fabio says Reinstate Monica
第一段故意加粗以便将大家的注意力集中在双指针的核心概念上,并谈论代码块:当您运行代码时,代码可能会包含一些打印错误,因为我没有检查或运行代码。我只是使用了我认为正确的概念。关于格式问题,我在代码块中没有看到任何问题。 - Aniruddha Sinha
我会尝试将您的注意力集中在代码块的一个注释上:“如果地址值没有显示,请更改格式说明符并将说明符从%d替换为%u”。 - Aniruddha Sinha

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接