有人可以向我解释多重引用和解除引用背后的概念吗?为什么以下程序将输出设为'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;
}
我读到连续使用'*'和'&'相互抵消,但这个解释没有提供上述代码中产生的两个不同输出背后的原因?
答案 0 :(得分:2)
第一个程序产生h
,因为&
和*
s"取消"彼此:"解除引用X"的地址给回X:
ptr
- 指向"hello"
literal *ptr
- 取消引用指向初始字符的指针,即初始字符 li>
&*ptr
指向初始字符的指针的解引用地址,即指向初始字符的指针,即ptr
本身等等。如您所见,一对*&
将您带回到您已经开始的位置,因此您可以从取消引用/获取地址表达式中删除所有这些对。因此,您的第一个程序printf
等同于
printf("%c\n", *ptr);
第二个程序有未定义的行为,因为指针正在传递给printf
,格式说明符为%c
。如果您将同一个表达式传递给%s
,则会打印出hello
这个词:
printf("%s\n", *&*&ptr);
答案 1 :(得分:1)
让我们来看看该计划的重要部分:
char *ptr = "hello";
指向char
指向字符串文字"hello"
的指针。现在,对于令人困惑的部分:
printf("%c\n", *&*&*ptr);
此处,%c
需要char
。让我们看一下*&*&*ptr
的类型。 ptr
是char*
。应用解除引用运算符(*
)会得到char
。将地址运算符应用于此char
会返回char*
。这会再次重复,最后,*
最后给我们一个char
,即字符串文字"hello"
的第一个字符,它会被打印出来。
*&*&ptr
中,您首先应用&
运算符,该运算符为char**
。在此上应用*
会返回char*
。这再次重复,最后,我们得到一个char*
。但是%c
需要char
,而不是char*
。因此,第二个程序根据C11标准(强调我的)展示Undefined Behavior:
7.21.6.1 fprintf函数
[...]
- 如果转换规范无效,则行为未定义。 282 如果任何参数不是相应转换规范的正确类型,则行为未定义。 < / LI> 醇>
所以,基本上,当你执行第二个程序时,任何事情都会发生。您的程序可能会崩溃,发出分段错误,输出奇怪的内容或执行其他操作。
顺便说一下,你说的是对的:我读到连续使用&#39; *&#39;和&#39;&amp;&#39;取消对方
答案 2 :(得分:0)
让我们分解*&*&*ptr
实际上是什么,但首先,请记住,当将*
应用于指针时,它会为您提供指针所指向的内容。另一方面,当将&
应用于变量时,它会为您提供该变量的内存地址。
现在,在稳定的基础上,让我们看看你在这里有什么:
ptr
是指向char
的指针,因此在执行*ptr
时,它会为您提供ptr
指向的数据,在这种情况下,ptr
指向字符串"hello"
,但是char
只能容纳一个字符,而不是整个字符串,对吧?所以,它指向这样一个字符串的开头,这是其中的第一个字符,即h
。
继续...... *&*&*ptr=*&*&(*ptr) = *&*&('h')= *&*(&'h') = *&*(ptr)=*&(*ptr) = *&('h')= *ptr = 'h'
如果你在下一个函数上应用相同的模式,我很确定你能搞清楚。
摘要:从右到左读取指针!