68

我目前正在重构/整理 C++ 项目中使用的一些旧 C 代码,并经常看到以下函数:

int f(void)

我倾向于写成:

int f()

是否有任何理由不在整个代码库中用 () 替换 (void) 以提高一致性,或者两者之间是否存在我不知道的细微差别?

更具体地说,如果 C++ 中的虚成员函数被描述为:

virtual int f(void)

派生类包括一个成员函数:

int f()

这是一个有效的覆盖吗?此外,我是否可能会遇到任何基于几乎相同签名的链接器问题?

4

6 回答 6

101

在 C 中,声明int f(void)是指返回不带参数的 int 的函数。声明int f()意味着一个返回 int 的函数,它接受任意数量的参数。因此,如果您有一个在 C 中不带参数的函数,则前者是正确的原型。

在 C++ 中,我认为int f(void)它已被弃用,并且int f()是首选,因为它特别意味着一个不带参数的函数。

于 2009-01-06T12:37:52.813 回答
21

添加到克里斯的回答中,根据我的经验,在 C 中使用int f()是不好的做法,因为您失去了编译器将函数的声明与其定义进行比较的能力,以确保正确调用它。

例如,以下代码是符合标准的 C:

#include <stdio.h>

void foo();

void bar(void) {
    foo();
}

void foo(int a) {
    printf("%d\n", a);
}

但它会导致未定义的行为,因为a没有传递给foo.

在 C++ 中,有两个版本foo:一个不带参数,另一个带int. 所以bar最终调用未定义的版本,这将导致链接器错误(假设foo任何地方都没有其他定义)。

于 2009-01-06T12:43:15.220 回答
18

之前的答案非常正确,但我链接到 David Tribble 的优秀页面,因为它对这个问题和许多其他问题给出了很好的解释。

亮点:

C 区分使用空参数列表声明的函数和使用仅包含 void 的参数列表声明的函数。前者是一个带有未指定数量参数的非原型函数,而后者是一个不带参数的原型函数。

另一方面,C++ 不区分这两个声明,并认为它们都意味着一个不带参数的函数。

对于打算编译为 C 或 C++ 的代码,此问题的最佳解决方案是始终使用显式 void 原型声明不带参数的函数。

空函数原型在 C99 中是一个弃用的特性(就像在 C89 中一样)。

可能值得注意的是 func(void) 语法在 C++ 中并未被弃用,但它通常被认为更像是一种 C 风格的习语。我认为我遇到的大多数 C++ 程序员都喜欢空参数列表。

引用 C++ 标准,第 8.3.5 节,第 2 段:

“如果 parameter-declaration-clause 为空,则函数不接受任何参数。参数列表 (void) 等效于空参数列表。除了这种特殊情况,void 不应是参数类型(尽管类型派生自 void ,如void*,可以)。”

没有提到任何一种形式都已被弃用。再次感谢 Tribble 先生出色的网站将我指向标准的正确部分。

于 2009-02-28T03:25:20.840 回答
2

C11 N1570标准草案

void f()已弃用,void f(void)推荐:

6.11.6 函数声明器

1 使用带空括号的函数声明符(不是原型格式参数类型声明符)是一个过时的特性。

简介

2 某些特性已经过时,这意味着它们可能会在本国际标准的未来修订版中被考虑撤销。由于它们的广泛使用,它们被保留,但不鼓励在新实现(用于实现特性)或新程序(用于语言 [6.11] 或库特性 [7.31])中使用它们。

详细讨论:https ://stackoverflow.com/a/36292431/895245

C++11 N3337 标准草案

既不void f(void)也不void f()被弃用。

void f(void)为与 C 兼容而存在。附录 C“兼容性”C.1.7 第 8 条:声明符

8.3.5 更改:在 C++ 中,使用空参数列表声明的函数不接受任何参数。在 C 中,空参数列表意味着函数参数的数量和类型未知。

由于void f()在 C 中已弃用并被void f(void)推荐,void f(void)只要 C++ 想要保持兼容性,它就会存在。

void f(void)并且void f()在 C++ 中是相同的。因此,void f(void)只有在您关心编写可在 C 和 C++ 下编译的代码时,更长的时间才有意义,这可能不值得。

详细讨论:https ://stackoverflow.com/a/36835303/895245

于 2016-04-25T08:36:56.697 回答
2

tl;博士:使用void

考虑到 C++ 的向后兼容性,以及下面确定的一些模糊性,我断言我们一直回到 K&R 和 ANSI C 以获得结论性答案:

int getline(void);
int copy(void)

由于 getline 和 copy 的特殊版本没有参数,逻辑会建议它们在文件开头的原型应该是getline()and copy()。但是为了与旧的 C 程序兼容,该标准将空列表作为旧式声明,并关闭所有参数列表检查;该词 void必须用于明确的空列表。[Kernighan & Richie,C 编程语言,1988 年,第 32-33 页]

和..

空参数列表的特殊含义是允许旧的 C 程序使用新的编译器进行编译。但是将它与新程序一起使用是个坏主意。如果函数接受参数,则声明它们;如果不带参数,请使用 void [ibid, Pg. 73]

我在这里将其余部分分解为单独的讨论: 在不带参数的函数声明中指定使用 void 是否解决了最令人烦恼的解析?

于 2017-01-17T18:00:56.110 回答
-1

在 C++ 中,int f(void)确实是一个已弃用的声明,它 100% 等同于int f(). 这同一个签名。在void这种情况下,与空白一样重要。这也意味着它们受单一定义规则(它们不会超载)和Derived::f(void)覆盖的约束Base::f()

不过,不要乱用类似的东西f(const void)。这种怪异的含义并没有太多共识。

于 2009-01-06T12:50:58.060 回答