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