代码之家  ›  专栏  ›  技术社区  ›  Khaled Alshaya

如何破译指针+数组的复杂声明?

  •  3
  • Khaled Alshaya  · 技术社区  · 15 年前

    虽然我用 std::vector 几乎一直以来,我都对尽可能多地理解指针感兴趣。我所说的例子:

    char* array[5]; // What does it mean?
    // 1) pointer to an array of 5 elements!
    // 2) an array of 5 pointers?
    

    我对这份声明的确切定义感兴趣。

    7 回复  |  直到 15 年前
        1
  •  3
  •   Mitch Wheat    15 年前

    不仅仅是指针和数组: How to interpret complex C/C++ declarations :

    开始阅读声明 最里面的圆括号,向右,然后 然后向左走。当你遇到 括号中,方向应为 颠倒的。一旦一切都在 括号已被解析,跳出 其中。一直到最后 已分析声明。

    左右一个小的零钱 规则:当你开始阅读 第一次声明,你 必须从标识符开始,并且 不是最里面的括号。

    你的例子是:

    char* array[5];
    

    是指向char的5个指针的数组。

        2
  •  3
  •   Captain Segfault    15 年前

    CDECL是一个很适合这种情况的程序。(尤其是在混合中添加函数指针时!)

    Type `help' or `?' for help
    cdecl> explain char* foo[5]
    declare foo as array 5 of pointer to char
    cdecl> declare bar as array 5 of pointer to function (integer, integer) returning char
    char (*bar[5])(int , int )
    
        3
  •  2
  •   Michael Burr    15 年前

    很久以前,我从杂志上的一篇文章中学到了顺时针/螺旋法则。以下是一篇介绍该技术的在线文章:

    这对我很有帮助,尽管我仍在努力处理一些有时会遇到的基于模板的可怕声明。

        4
  •  2
  •   lhenrygr    15 年前

    在C/C++中读取一个类型的一般过程是:

    1. 标识最终类型,它可以是基本类型或typedef标识符,并且在示例中可以有类型修饰符,如const、volatile等,即“char”。
    2. 以与表达式中相同的优先顺序将运算符应用于标识符。这些运算符可以是*(取消引用)、[](索引)和()(调用函数)。

    在最初的语法哲学中,您的示例应该写为“char*array[5]”,标识符是“array”,运算符是[](index),然后是*(取消引用)。

    然后,声明读起来像一个契约,“如果您按照这个顺序应用这些操作符,那么您将得到一个最终类型的对象”。

    在您的例子中,完整的句子是“如果您索引变量”array“,然后取消对结果表达式的引用,您将得到一个char”。

    您也可以这样认为:“如果您对变量“array”进行索引,那么您将得到一个对象,这样,如果您取消对它的引用,您将得到一个字符。”

    技巧主要是跟踪这样一个事实,即[]和()的优先级高于*。可以使用括号控制运算符顺序,就像对正则表达式一样。

        5
  •  1
  •   Philip Davis    15 年前

    char*是类型,您有5个数组。

        6
  •  1
  •   DevFred    15 年前

    []的优先级高于*,这就是为什么它是指针数组,而不是相反。

        7
  •  1
  •   mustafabar    15 年前

    您总是从右向左读取指针,将“*”解释为指针。 例如char**a[5]是一个指向字符指针的5个指针数组…