f(void) 在现代 C 和 C++ 中是否已弃用?

发布于 2024-07-10 12:25:58 字数 381 浏览 11 评论 0 原文

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

int f(void)

我倾向于将其写为:

int f()

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

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

virtual int f(void)

并且派生类包含成员函数:

int f()

这是有效的重写吗? 此外,我是否可能会遇到基于几乎相同签名的链接器问题?

I'm currently refactoring/tidying up some old C code used in a C++ project, and regularly see functions such as:

int f(void)

which I would tend to write as:

int f()

Is there any reason not to replace (void) with () throughout the codebase in order to improve consistency, or is there a subtle difference between the two that I am unaware of?

More specifically, if a virtual member function in C++ is described as:

virtual int f(void)

and a derived class includes a member function:

int f()

is this a valid override? Additionally, am I likely to encounter any linker problems based on almost identical signatures?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

治碍 2024-07-17 12:25:58

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

在 C++ 中,我认为 int f(void) 已被弃用,而 int f() 是首选,因为它具体表示不带参数的函数。

In C, the declaration int f(void) means a function returning int that takes no parameters. The declaration int f() means a function returning int that takes any number of parameters. Thus, if you have a function that takes no parameters in C, the former is the correct prototype.

In C++, I believe int f(void) is deprecated, and int f() is preferred, as it specifically means a function that takes no parameters.

酒儿 2024-07-17 12:25:58

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

例如,以下代码是符合标准的 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 的其他定义)。

To add to Chris's answer, using int f() is bad practice in C, in my experience, since you lose the compiler's ability to compare the function's declaration to its definition, to ensure that it will be called correctly.

For example, the following code is standards-compliant C:

#include <stdio.h>

void foo();

void bar(void) {
    foo();
}

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

But it results in undefined behavior, since a was not passed to foo.

In C++, there are two versions of foo: one that takes no arguments and one that takes an int. So bar winds up calling the undefined version, which would result in a linker error (assuming there are no other definitions of foo anywhere).

你是暖光i 2024-07-17 12:25:58

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

亮点:

C 区分函数
使用空参数列表声明
和一个用 a 声明的函数
参数列表仅包含
空白。 前者是一个未原型化的
函数取未指定的数字
的参数,而后者是
原型函数不采用
论据。

另一方面,C++ 不做任何事情
两者之间的区别
声明并考虑它们
表示不取任何值的函数
论据。

对于旨在实现的代码
编译为 C 或 C++,最好
解决这个问题的方法是始终
声明不带参数的函数
具有显式的 void 原型。

空函数原型是
C99 中已弃用的功能(因为它们
在 C89 中)。

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

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

“如果参数声明子句为空,则函数不带参数。参数列表 (void) 相当于空参数列表。除了这个特殊的在这种情况下,void 不应是参数类型(尽管从 void 派生的类型,例如 void*,可以)。”

没有提到这两种形式都已被弃用。 再次感谢 Tribble 先生出色的网站为我指出了该标准的正确部分。

The previous answers are quite correct, but I'm linking to David Tribble's excellent page as it gives a great explanation on this and many other issues.

The highlights:

C distinguishes between a function
declared with an empty parameter list
and a function declared with a
parameter list consisting of only
void. The former is an unprototyped
function taking an unspecified number
of arguments, while the latter is a
prototyped function taking no
arguments.

C++, on the other hand, makes no
distinction between the two
declarations and considers them both
to mean a function taking no
arguments.

For code that is intended to be
compiled as either C or C++, the best
solution to this problem is to always
declare functions taking no parameters
with an explicit void prototype.

Empty function prototypes are a
deprecated feature in C99 (as they
were in C89).

It's perhaps worth noting that the func(void) syntax is not deprecated in C++, but it's commonly considered more of a C-style idiom. I think most C++ programmers I've run across prefer the empty parameter list.

A quote from the C++ standard, section 8.3.5, paragraph 2:

"If the parameter-declaration-clause is empty, the function takes no arguments. The parameter list (void) is equivalent to the empty parameter list. Except for this special case, void shall not be a parameter type (though types derived from void, such as void*, can)."

There's no mention that either form is deprecated. Thanks again to Mr. Tribble's excellent website for pointing me to the correct section of the standard.

过期情话 2024-07-17 12:25:58

C11 N1570标准草案< /strong>

void f() 已弃用,建议使用 void f(void)

6.11.6 函数声明符

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

简介

2 某些功能已过时,这意味着它们可能会被考虑淘汰
在本国际标准的未来修订中撤回。 他们被保留是因为
它们的广泛使用,但它们在新的实现中的使用(用于实现
不鼓励使用新程序(针对语言 [6.11] 或库功能 [7.31])。

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

C++11 N3337 标准草案 两者

都不是 < code>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),因此只要 C++ 存在,void f(void) 就会存在想要保持兼容性。

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

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

C11 N1570 standard draft

void f() is deprecated, void f(void) recommended:

6.11.6 Function declarators:

1
The use of function declarators with empty parentheses (not prototype-format parameter
type declarators) is an obsolescent feature.

Introduction:

2 Certain features are obsolescent, which means that they may be considered for
withdrawal in future revisions of this International Standard. They are retained because
of their widespread use, but their use in new implementations (for implementation
features) or new programs (for language [6.11] or library features [7.31]) is discouraged.

Detailed discussion: https://stackoverflow.com/a/36292431/895245

C++11 N3337 standard draft

Neither void f(void) nor void f() are deprecated.

void f(void) exists for compatibility with C. Annex C "Compatibility" C.1.7 Clause 8: declarators:

8.3.5 Change: In C ++ , a function declared with an empty parameter list takes no arguments. In C, an empty
parameter list means that the number and type of the function arguments are unknown.

Since void f() is deprecated in C and void f(void) recommended, void f(void) will exist for as long as C++ wants to maintain compatibility.

void f(void) and void f() are the same in C++. So the longer void f(void) only makes sense if you care about writing code that compiles under both C and C++, which is likely not worth it.

Detailed discussion: https://stackoverflow.com/a/36835303/895245

揽月 2024-07-17 12:25:58

tl;dr:使用void

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

int getline(void);
int copy(void)

由于 getline 和 copy 的专门版本没有参数,
逻辑表明他们的原型位于文件的开头
应该是 getline()copy()。 但为了兼容
较旧的 C 程序标准将空列表视为旧式
声明,并关闭所有参数列表检查; 这个单词
void 必须用于显式空列表。
[克尼根和 Richie,C 编程语言,1988 年,第 32-33 页]

和..

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

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

tl;dr: use void.

Given the backward compatibility in C++, and the bit of ambiguity identified below, I assert that we go all the way back to K&R and ANSI C for a conclusive answer:

int getline(void);
int copy(void)

Since the specialized versions of getline and copy have no arguments,
logic would suggest that their prototypes at the beginning of the file
should be getline() and copy(). But for compatibility with
older C programs the standard takes an empty list as an old-style
declaration, and turns off all argument list checking; the word
void must be used for an explicitly empty list.
[Kernighan & Richie, the C programming language, 1988, Pgs 32-33]

and..

The special meaning of the empty argument list is intended to permit
older C programs to compile with new compilers. But it's a bad idea to
use it with new programs. If the function takes arguments, declare
them; if it takes no arguments, use void [ibid, Pg. 73]

I broke the rest into a separate discussion here:
Does specifying the use of void in the declaration of a function that takes no arguments address The Most Vexing Parse?

鹿! 2024-07-17 12:25:58

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

不过,不要搞乱像 f(const void) 这样的东西。 这种奇怪的现象意味着什么,目前还没有达成共识。

In C++, int f(void) is indeed a deprecated declaration which is 100% equivalent to int f(). It is the same signature. The void in this context is as significant as e.g. whitespace. That also means that they are subject to the One Definition Rule (they don't overload) and Derived::f(void) overrides Base::f().

Don't mess with stuff like f(const void), though. There's not a lot of consensus what that kind of weirdness means.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文