【问题标题】:About pointer and reference syntax关于指针和引用语法
【发布时间】:2009-12-22 19:06:01
【问题描述】:

虽然我知道我不是唯一一个遇到这个问题的人,但很尴尬。

多年来,我一直在断断续续地使用 C/C++。我在掌握地址、指针、指向指针的指针和引用的概念方面从来没有遇到过问题。

然而,我确实经常发现自己在用 C 语法表达它们时遇到了麻烦。不是声明或取消引用之类的基础知识,而是更常见的事情,例如获取指向指针的地址或指向引用的指针等。基本上任何超出规范的间接级别或两个级别的东西。通常我会摸索各种运算符的半逻辑组合,直到找到正确的组合。

很明显,我错过了一条或两条可以简化并使其全部到位的规则。所以我想我的问题是:您是否知道某个网站或参考资料可以清晰而深入地涵盖此问题?

【问题讨论】:

  • 如果你能提供一些具体的例子来说明让你不快的表达方式,那将会很有帮助。

标签: c++ c


【解决方案1】:

我不知道任何网站,但我会尝试用非常简单的术语来解释它。您只需要了解三件事:

  1. variable 将包含变量的内容。这意味着如果变量是一个指针,它将包含它指向的内存地址。
  2. *variable(仅对指针有效)将包含变量指向的内容。如果它指向的变量是另一个指针ptr2,那么*variableptr2将是同一个东西; **variable*ptr2 也是一回事。
  3. &variable 将包含变量的内存地址。如果是指针,则为指针本身的内存地址,NOT指向的变量或指向的变量的内存地址。

现在,让我们看一个复杂的例子:

    void **list = (void **)*(void **)info.List;

list 是一个指向指针的指针。现在让我们从末尾开始检查作业的正确部分:(void **)info.List。这也是一个指向指针的指针。

然后,您会看到 *:*(void **)info.List。这意味着这是指针 info.List 指向的值。

现在,整个事情:(void **)*(void **)info.List。这是指针 info.List 指向的值 (void **)。

【讨论】:

    【解决方案2】:

    我发现right-left-right rule 很有用。它告诉您如何阅读声明,以便按顺序获取所有指针和引用。例如:

    int *foo();
    

    使用 right-left-right 规则,您可以将其翻译成英文为“foo 是一个返回指向整数的指针的函数”。

    int *(*foo)();  // "foo is a pointer to a function returning a pointer to an int"
    int (*foo[])();  // "foo is an array of pointers to functions returning ints"
    

    大多数关于右-左-右规则的解释都是为 C 而不是 C++ 编写的,因此它们倾向于省略引用。在这种情况下,它们就像指针一样工作。

    int &foo;  // "foo is a reference to an integer"
    

    【讨论】:

    • 这让一些事情变得简单。我想要一个指针的引用,但不记得语法,是int &* ptr 还是int *& ptr?从右到左读,“ptr 是一个指向 int 的指针的引用”,第二个显然是正确的。
    【解决方案3】:

    当事情变得混乱时,Typedef 可以成为你的朋友。这是一个例子:

    typedef const char * literal_string_pointer;
    typedef literal_string_pointer * pointer_to_literal_string_pointer;
    void GetPointerToString(pointer_to_literal_string_pointer out_param)
    {
        *out_param = "hi there";
    }
    

    【讨论】:

      【解决方案4】:

      你需要知道的是,获取一个对象的地址会返回一个指向该对象的指针,而取消引用一个对象需要一个指针并将其转换为它所指向的对象。

      T x;
      A a = &x; // A is T*
      B b = *a; // B is T
      C c = &a; // C is T**
      D d = *c; // D is T*
      

      本质上,& 运算符采用T 并为您提供T** 运算符采用T* 并为您提供T,这同样适用于更高级别的抽象例如 在T* 上使用& 会给你一个T**

      另一种思考方式是& 运算符将* 添加到类型中,而* 删除一个,从而导致&&*&**i == i 之类的事情。

      【讨论】:

        【解决方案5】:

        我不确定您在寻找什么,但我发现记住 operator precedence and associativity rules 会很有帮助。就是说,如果您感到困惑,不妨添加更多括号来消除歧义,即使这只是为了您的利益而不是编译器的利益。

        编辑:我想我现在可能会更好地理解您的问题。我喜欢把指针链想象成一个堆栈,底部的值。取消引用运算符 (*) 将您从堆栈中弹出,最后您可以在其中找到值本身。引用运算符 (&) 允许您将另一个级别的间接推送到堆栈上。请注意,再移一步总是合法的,但尝试取消引用该值类似于弹出一个空堆栈。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-08-06
          • 2019-06-11
          • 2017-11-03
          • 2019-10-15
          • 2012-11-04
          相关资源
          最近更新 更多