难道没有人一劳永逸地解释typedef的语法吗?

Couln't someone explain the grammar of typedef once and for all?

本文关键字:语法 typedef 解释 没有人 一劳永逸      更新时间:2023-10-16

我知道如何为简单类型声明别名,比如类类型、基元类型,以及指向返回这些类型值的函数的指针。实际上:

typedef int T; //T := int
typedef int* T; // T := int*
typedef int (*T)() //T := int (*)(). OK, but it's a bit unclear to me. 
                   //Seems a little bit confused
typedef int (*T[])() // T := array of int(*)(). Totally confused. What the hell is going on?

我不明白编译器应该如何解析这样的typedef声明。也许有人可以解释一下我举的这个简单的例子?我知道,c++引入了别名贴花如下:

using T = int*;

它可能更可读,但现在我只对typedef贴花感兴趣。

typedef的语法与变量的语法完全相同公告唯一的区别是所声明的名称变成类型的别名,而不是对象、引用或函数。

注意,typedef是公告完整的声明由三部分组成:属性说明符seq(C++11新增)、一个decl说明符seq[/em>和一个init声明符列表。原则上,所有零件都可以空,但仅适用于某些类型的声明;在例如,typedef,只有属性说明符seq可以为空。要理解一个声明,您必须首先将其分解为三个部分:属性说明符seq很简单:它将始终是在[[...]]中,您不会经常看到它,因为它是非常新的,并且仅用于特殊用途。我们暂时忽略它。这个decl说明符seq是一系列关键字或符号,用于命名type(尽管某些关键字后面有特殊情况,如structenum);只需收集所有符号,直到遇到不是关键字或类型的东西。包括CCD_ 8。顺序这并不重要,所以:

int typedef const CI;

将是完全合法的,尽管肯定不是典型的。如果如果存在关键字typedef,则声明为typedef(意味着其他一些关键字,如externstatic,不是允许)。decl说明符给出英语中的最终类型类型的表达式。

下面的所有内容都是init声明符seq的一部分,它是init声明符的逗号分隔列表。typedef需要至少有一个init声明符,事实上,它不允许init部分,所以它只是一个声明符(但实际上可能有几个,尽管据我所知,微软是唯一一家致力于混淆)。每个声明符基本上都是一个表达式右边的运算符(()[])优先于左边的运算符(*&),括号用于修改优先级。所以,如果你有类似(&ra)[10]ra的东西是对…的数组[10]的引用。。。什么:wever类型由decl指定。或者,如果括号中没有给出优先级:*ra[10]是指向…的指针数组[10]

typedef s遵循与变量声明相同的规则,因此我将首先介绍这些。预期的原则是:如果您将声明键入为表达式,您将获得类型。让我们来分析一下这个变量:

int (*a[])();

现在我们一步一步地进行:

键入CCD_ 22得到CCD_。用x1代替(*a[42])x1()属于int类型,因此很明显,x1(即(*a[42]))是一个不带参数并返回int的函数。

因此,a[42]必须是指向"不接受参数并返回int的函数"的指针

因此,a必须是一个"指向不带参数并返回int的函数的指针"的数组

对于typedefs,唯一的区别是,我们谈论的不是变量a,而是其类型。所以typedef int (*T[])();的意思是:

T是变量a在声明为int (*a[])(); 时的类型

因此,在您的情况下,T是"一个指向函数的指针数组,不带参数,返回-int。"

我不明白编译器应该如何解析这样的typedef声明。

由于这似乎是一个令人关注的主要话题,我决定添加一个重要的说明,从更高层次概述这是如何实现的。

由于该语言中现在有上下文,因此在解析时需要获得有关该语言的语法和语义的信息。

在您的示例中,原始解决方案使用了lex hack,这是C++编译器设计人员为解决由于typedef令牌而导致语言不再与上下文无关的问题而实现的方法的实际名称。这种"破解"的基本思想是从语义分析器到lexer有一个额外的反向通道来提供所需的上下文。

还有其他方法可以解决解析上下文敏感语法的问题,例如无词法解析