【问题标题】:Multiple Reference and Dereference in CC中的多重引用和取消引用
【发布时间】:2015-08-06 01:31:52
【问题描述】:

有人能清楚地解释一下多重引用和取消引用背后的概念吗?为什么下面的程序输出为 'h' ?

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

getchar();
return 0;
} 

而不是 this ,而是产生 'd' ?

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

getchar();
return 0;
}

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

【问题讨论】:

  • “使用 '*' 和 '&' 会互相抵消”所以试试printf("%c\n", ptr);。想想。
  • 在第二种情况下,您首先将& 运算符应用于指针本身,因此您将获得char **。然后你继续引用和取消引用,所以你最终打印指针值而不是它指向的值。
  • @FilipeGonçalves 这就是答案

标签: c pointers reference dereference


【解决方案1】:

第一个程序产生h,因为&s 和*s 相互“取消”:“取消引用X 的地址”返回X:

  • ptr - 指向 "hello" 字面量首字母的指针
  • *ptr - 取消引用指向初始字符的指针,即初始字符​​li>
  • &*ptr指向初始字符的指针的解引用地址,即指向初始字符的指针,即ptr本身

等等。如您所见,一对*& 将您带回到您开始的位置,因此您可以从取消引用/获取地址表达式中消除所有此类对。因此,您的第一个程序的printf 相当于

printf("%c\n", *ptr);

第二个程序有未定义的行为,因为指针被传递给printf,格式说明符为%c。如果您将相同的表达式传递给%s,则会打印出单词hello

printf("%s\n", *&*&ptr);

【讨论】:

    【解决方案2】:

    让我们来看看程序的重要部分:

    char *ptr = "hello";
    

    创建一个指向char 的指针,该指针指向字符串文字"hello"。现在,对于令人困惑的部分:

    printf("%c\n", *&*&*ptr);
    

    在这里,%c 需要 char。让我们看看*&*&*ptr 是什么类型。 ptrchar*。应用解引用运算符 (*) 会得到 char。将地址运算符应用于此char 将返回char*。这再次重复,最后,最后的* 给了我们一个char,这是字符串文字"hello" 的第一个字符,它被打印出来。


    在第二个程序中,在*&*&ptr 中,您首先应用& 运算符,它给出char**。在此应用* 会返回char*。这再次重复,最后,我们得到一个char*。但是%c 需要char,而不是char*。因此,第二个程序根据 C11 标准展示了Undefined Behavior(重点是我的):

    7.21.6.1 fprintf 函数

    [...]

    1. 如果转换规范无效,则行为未定义。282如果任何参数不是相应转换规范的正确类型,则行为未定义。

    所以,基本上,当您执行第二个程序时,任何事情都可能发生。您的程序可能会崩溃、发出分段错误、输出奇怪的东西或执行其他操作。


    顺便说一句,你说得对:

    我读到连续使用 '*' 和 '&' 相互抵消

    【讨论】:

      【解决方案3】:

      让我们分解*&*&*ptr 的实际含义,但首先,请记住,将* 应用于指针时,它会为您提供指针所指向的内容。另一方面,当将& 应用于变量时,它会为您提供该变量在内存中的地址。

      现在,在取得稳定的基础后,让我们看看你在这里有什么: ptr 是指向 char 的指针,因此在执行 *ptr 时,它会为您提供 ptr 指向的数据,在这种情况下,ptr 指向字符串 "hello",但是,@987654330 @ 只能容纳一个字符,而不是整个字符串,对吧?所以,它指向这样一个字符串的开头,也就是其中的第一个字符,也就是h

      继续...*&*&*ptr=*&*&(*ptr) = *&*&('h')= *&*(&'h') = *&*(ptr)=*&(*ptr) = *&('h')= *ptr = 'h'

      如果你在下一个函数上应用相同的模式,我很确定你能弄明白。

      摘要:从右向左读取指针!

      【讨论】:

        猜你喜欢
        • 2012-12-22
        • 2016-12-01
        • 2016-07-06
        • 2017-01-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多