首页 > 解决方案 > 没有无类型参数的调用方法

问题描述

我注意到 C 中的一些我不太理解的行为。如果我使用未指定类型的参数定义函数并在没有任何参数的情况下调用它,则代码会编译但会发出警告,指出参数的类型默认为int.

void f(i) {
    printf("%d", i);
}
int main(void) {
    f();
}

如果我在 godbolt 上运行它,我会收到预期的编译器警告,并且执行会打印 1 到stdout.

但是,如果我定义了相同的方法,但将参数显式声明为int,编译器会为使用太少参数调用的函数引发错误。

void f(int i) {
    printf("%d", i);
}
int main(void) {
    f();
}

在 Godbolt 上编译它会产生error: too few arguments to function 'f'.

这种行为在所有现代版本的 gcc 和 clang 中都是一致的。为什么指定参数的类型会使这成为编译器错误?另外,是否定义了第一个示例的行为?gcc 和 clang 总是为 1 的事实i会让我认为这是故意的。如果是这样,为什么?

标签: ccompilation

解决方案


两种类型的函数原型:

  1. 原版,称为“K&R”[来自 C 的创造者 Kernighan & Ritchie]。
  2. 现代的,被称为“ANSI”[来自 ANSI 标准化委员会]。

起初,我们只有 K&R:

#include <stdio.h>

void
f(i)
int i;
{

    printf("%d\n",i);
}

int
main(void)
{

    f();

    return 0;
}

当 C 语言标准化时,添加了另一种形式的函数原型:

#include <stdio.h>

void
f(int i)
{

    printf("%d\n",i);
}

int
main(void)
{

    f();

    return 0;
}

这些是函数的定义方式。但是,如果我们放入f一个单独的文件,我们会留下原型声明:

这是K&R:

#include <stdio.h>

void f();

int
main(void)
{

    f();

    return 0;
}

这是ANSI:

#include <stdio.h>

void f(int i);

int
main(void)
{

    f();

    return 0;
}

如果您仔细查看 K&R 原型,则无法辨别i.

ANSI 纠正了这个缺陷。如果您查看该原型,则类型为 fori被明确指定为int


因此,为了回答您的问题,在您的示例中,没有的语法int是 K&R 样式原型/定义。当我们添加int时,它是一个 ANSI 原型/定义。

自 1990 年代 (IIRC) 的某个时候以来,K&R 就没有在新代码中广泛使用。但是,编译器理解它是为了向后兼容在 ANSI 之前编写的代码。

旁注:我在 1981 年开始使用 C 编程,所以我使用 K&R 至少十年(这篇文章的很多内容来自 [fading] memory)。在我得到一个支持 ANSI 的编译器之后,在新代码上尝试了 ANSI 原型几个月后,我将所有旧代码都转换为使用 ANSI。


了解更多信息 ...

请参阅:函数声明:K&R 与 ANSI

并且,函数声明与原型的替代 (K&R) C 语法


推荐阅读