c - 没有无类型参数的调用方法
问题描述
我注意到 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
会让我认为这是故意的。如果是这样,为什么?
解决方案
有两种类型的函数原型:
- 原版,称为“K&R”[来自 C 的创造者 Kernighan & Ritchie]。
- 现代的,被称为“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
推荐阅读
- marklogic - 使用 XML 文档中的值搜索 Xpath 并从 Marklogic 获取文档 URI
- python - 如何为 Jenkins 设置 Python 目录结构?
- apache-spark - Spark Streaming 跨批次维护流数据
- c++ - 阅读简单的 .txt 时,我得到了垃圾值
- python - 如何读取在同一列中具有多个 json 值的数据框
- sql - SQL Server - 在函数中创建超时异常
- sql - 使用 WHERE 和 COUNT 在 sql 查询中返回错误值
- python - Python:将多个二进制列转换为单个分类列
- python - 字符串文字以单引号开头并以三引号结尾,它如何有效?
- linux - GREP 或 AWK:在每行的前 N 个字符中搜索,并输出匹配模式的周围行