C语言中的多重引用与去引用

C语言中的多重引用与去引用,c,pointers,reference,dereference,C,Pointers,Reference,Dereference,有人能给我解释一下多重引用和去引用背后的概念吗?为什么以下程序的输出为“h” int main() { char *ptr = "hello"; printf("%c\n", *&*&*ptr); getchar(); return 0; } 不是这个,而是产生“d” int main() { char *ptr = "hello"; printf("%c\n", *&*&ptr); getchar(); return 0; } 我读到连续使用“*”和“

有人能给我解释一下多重引用和去引用背后的概念吗?为什么以下程序的输出为“h”

int main()
{
char *ptr = "hello";
printf("%c\n", *&*&*ptr);

getchar();
return 0;
} 
不是这个,而是产生“d”

int main()
{
char *ptr = "hello";
printf("%c\n", *&*&ptr);

getchar();
return 0;
}

我读到连续使用“*”和“&”会相互抵消,但这个解释并没有提供在上述代码中生成两个不同输出的原因

让我们看一下该计划的重要部分:

char *ptr = "hello";
生成指向char的指针,该指针指向字符串文本hello。现在,让人困惑的是:

printf("%c\n", *&*&*ptr);
这里,%c需要一个字符。让我们看看什么类型的*&*&*ptr。ptr是一个字符*。应用解引用运算符*将生成一个字符。将运算符地址应用于此字符将返回字符*。这会再次重复,最后,结尾的*给我们一个char,字符串literal hello的第一个字符,它会被打印出来。 在第二个程序中,在*&*&ptr中,首先应用&运算符,它给出一个char**。对其应用*将返回字符*。这是重复了一遍,最后,我们得到一个字符*。但是%c需要的是字符,而不是字符*。因此,第二个程序按照C11标准显示:

7.21.6.1 fprintf功能

[……]

如果转换规范无效,则行为未定义。282如果任何参数不是相应转换规范的正确类型,则行为未定义。 所以,基本上,当你执行第二个程序时,任何事情都可能发生。您的程序可能会崩溃、发出分段错误、输出奇怪的内容或执行其他操作

顺便说一句,你说得对:


我读到连续使用“*”和“&”会相互抵消


第一个程序生成h,因为&s和*s相互抵消:取消对X地址的引用会返回X:

ptr-指向hello literal的初始字符的指针 *ptr-指向初始字符(即初始字符)的指针的取消引用 &*ptr指向初始字符的指针的解引用地址,即指向初始字符的指针,即ptr本身 等等。如您所见,pair*&将返回到您开始的位置,因此您可以从解引用/获取地址表达式中删除所有这类对。因此,您的第一个程序的printf相当于

printf("%c\n", *ptr);
第二个程序具有未定义的行为,因为正在向printf传递一个指针,其格式说明符为%c。如果将相同的表达式传递给%s,则会打印单词hello:

printf("%s\n", *&*&ptr);
让我们来分析一下*&*&*ptr实际上是什么,但是首先,请记住,当将*应用于指针时,它会给出该指针指向的内容。另一方面,当对变量应用&时,它会为您提供该变量在内存中的地址

现在,在获得稳定的基础后,让我们看看这里有什么: ptr是一个指向字符的指针,因此当执行*ptr时,它会给你ptr指向的数据,在本例中,ptr指向一个字符串hello,然而,一个字符只能包含一个字符,而不是整个字符串,对吗?所以,它指向这样一个字符串的开头,它是其中的第一个字符,也就是h

继续…*&*&*&*ptr=*&*&*&*ptr=*&*&*&*&*&'h'=*&*ptr=*&*ptr=*&*ptr=*&'h'=*ptr='h'

如果你在下一个函数上应用相同的模式,我很确定你能找到它


小结:从右到左阅读指针

使用“*”和“&”会相互取消,因此请尝试printf%c\n,ptr;。想想看,在第二种情况下,首先将&运算符应用于指针本身,这样就得到了一个char**。然后继续引用和取消引用,最后打印的是指针值,而不是指针指向的内容。@FilipeGonçalves这就是答案