在语法上不可能知道f / g是函数调用还是类型转换而不知道它们是如何声明的。编译器是否知道解析步骤中的差异,或者他们通常在第二次通过中解决这个问题?
void f(int x){};
typedef short g;
int main(void){
((f)(1));
((g)(1));
return 0;
}
答案 0 :(得分:6)
C的早期版本(在K& R的第一版于1978年出版之前)没有typedef
功能。在该C版本中,始终可以在语法上识别类型名称。 int
,float
,char
,struct
等是关键字;类型名称的其他元素是标点符号,例如*
和[]
。 (解析器可以区分不是关键字的关键字和标识符,因为它们只有很小且固定的数量。)
添加typedef
时,必须将其加入到现有语言中。 typedef
为现有类型创建新名称。该名称是单个标识符 - 与语法不同于任何其他普通标识符。
C编译器在解析其输入时必须维护一个符号表。当遇到标识符时,需要查询符号表以确定它是否是类型名称。没有这些信息,语法就不明确了。
从某种意义上说,typedef
声明可以被认为是创建一个新的临时关键字。但它们是可以被内部范围中的新声明隐藏的关键字。
例如:
{
typedef short g;
/* g is now a type name, and the parser has
* to treat it almost like a keyword
*/
{
int g;
/* now g is an ordinary identifier as far as the parser is concerned */
}
/* And now g is a type name again */
}
解析C很难。
答案 1 :(得分:4)
我认为他们懒洋洋地这样做:每当解析一个令牌时,下一个令牌的解析会被延迟,直到知道该符号的语义信息为止。然后,当解析下一个标记时,编译器已经知道被引用的符号是否是类型名称(它必须先前已声明),并且可以相应地执行。 (因此在这种方法中,语义和句法分析交织在一起,不能分开。)