3

我正在阅读“C 中的编译器设计”一书。在基础部分中,我发现词法分析器的 ac 片段是这样的 -

static int Lookahead = -1;
int match(token)
int token;
{
 if(Lookahead == -1)
    Lookahead = lex();

 return token == Lookahead;
}

void advance(){
   Lookahead = lex();
}

我对这个 match 函数如何在 gnu gcc 上编译感到困惑。所以我写了一个看起来像的函数

int a(token)
int token;
{
 printf("Value of token is %d", token);
}
int main()
{
 printf("Hello world!\n");
 a(1);
 return 0;
}

我得到以下输出-

你好世界!代币价值为 1

但我不明白该函数声明背后的原因。以这种方式声明函数有什么好处?以及token的价值如何为1?为什么它不是编译错误?它是C中的某种函数声明吗?

感谢您检查我的问题。任何形式的帮助都会很棒。

4

3 回答 3

6

它是一种陈旧且已弃用的 K&R 函数声明风格。

int match(token)
int token;
{
    // Function body
}  

相当于

int match(int token)
{
    // Function body
}    

除了以前,编译器不会检查函数是否使用正确数量的参数调用,也不会检查参数的类型。它依赖于默认参数提升。
C89 和 C99 也支持这种风格。

于 2015-02-22T08:02:02.323 回答
4

这是 Kernighan 和 Ritchie 首次开发 C 编程语言时用来声明 C 函数的原始方式。它被称为“K&R C”

C 经历了一个标准化过程,这种形式的函数声明已更改为您习惯的形式。

http://en.wikipedia.org/wiki/The_C_Programming_Language页面上,这本书的第一版会有旧式的函数声明,我认为它在第二版中被删除了。

于 2015-02-22T08:03:36.723 回答
2

原始 K&R C 中的函数定义更简单。在您的示例中,函数参数标记的类型声明实际上是多余的。代码可以这样简化:

static int Lookahead = -1;
int match(token) {
    if (Lookahead == -1)
        Lookahead = lex();
    return token == Lookahead;
}
void advance(){
   Lookahead = lex();
}

事实上,函数返回类型和变量类型也默认为 int,void 尚未发明,return 语句是可选的......导致进一步简化:

static Lookahead=-1;
match(token){
  if(Lookahead==-1) Lookahead=lex();
  return token==Lookahead;
}
advance(){Lookahead=lex();}

这种原始风格更紧凑,但很容易出错,并且不再受到现代编译器的支持。您的示例中的函数定义语法仍然受支持,但被认为已过时并且可能在某个时候消失。

于 2015-02-22T09:12:21.980 回答