c - `int foo() {}` 与 `int foo(void) {}` 在声明 `int foo(void);` 之后的定义
问题描述
注意:这与 c99 中的 func() vs func(void)不同,因为这里的问题专门询问了在有效声明之后实现零参数函数。
零参数的实现是否应该包含void
关键字?具体来说,C标准对下面两个函数的实现有什么要说的吗?请注意,foo1
和foo2
都被声明为零参数函数;唯一的区别在于实现,而不是声明:
#include <stdio.h>
int foo1(void); // inform compiler that foo1 and foo2 are zero-args fns.
int foo2(void);
int main() {
printf("%d\n", foo1());
printf("%d\n", foo2());
return 0;
}
int foo1(void) { return 22; }
int foo2() { return 22; }
我注意到gcc -Wall -std=c99 -Wpedantic foo.c -o foo
编译和执行没有任何警告或错误,但是是否有任何违反标准的行为?
解决方案
您发布的代码是正确的。int foo2(void);
声明foo2
不带参数,并形成一个原型。
函数定义必须与此兼容;并且带有空括号的定义与此原型兼容。这是在 C11 6.7.6.3/15 中指定的,这是一口:
对于要兼容的两种函数类型,两者都应指定兼容的返回类型。此外,参数类型列表(如果两者都存在)应在参数数量和省略号终止符的使用方面达成一致;相应的参数应具有兼容的类型。如果一种类型具有参数类型列表,而另一种类型由不属于函数定义的函数声明符指定且包含空标识符列表,则参数列表不应有省略号终止符,并且每个参数的类型应与应用默认参数提升所产生的类型兼容。如果一种类型具有参数类型列表,而另一种类型由包含(可能为空)标识符列表的函数定义指定,则两者在参数数量上应一致,并且每个原型参数的类型应与类型兼容这是由于将默认参数提升应用于相应标识符的类型而产生的。(在类型兼容性和复合类型的确定中,每个声明为函数或数组类型的参数被视为具有调整后的类型,每个声明为合格类型的参数被视为具有其声明类型的非限定版本。)
关于这一点有这么多文字的原因是C最初只有K&R风格的函数,然后添加了原型。因此,必须有文字来涵盖 K&R 风格与原型风格混合的所有可能组合。以我的粗体部分开头的部分是指当函数先前已使用原型声明时使用 K&R 样式的函数定义。
同样相关:在 C11 (6.11.6) 中使用空括号已过时。
某些特性已经过时,这意味着它们可能会在本国际标准的未来修订版中被考虑撤销。由于它们的广泛使用,它们被保留下来,但不鼓励在新的实现或新程序中使用它们。
推荐阅读
- react-native - 在本机反应中动态更改折叠手风琴背景颜色的最佳方法是什么
- batch-file - 当子文件夹包含 .one 文件时,如何递归删除文件并跳过删除?
- amazon-web-services - 将第三方应用程序与 Jira 集成的方法有哪些?
- c - 在初始化期间正确关闭 Libuv 循环
- python - 修改wso2sp的基础镜像后无法创建容器
- sql - 如何在某些条件下计算选定行中的值 - Potgresql
- python-3.x - 将多维numpy数组的元素转换为float32
- java - 使用@Transactional 注释的方法内部没有捕获异常
- javascript - 存储复杂对象并在不同状态下对其进行维护
- java - 如何使用在浏览器中打开的 java 下载 xml 文件?