Is f(void) deprecated in modern C and C++?

C++CRefactoringVoid

C++ Problem Overview


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?

C++ Solutions


Solution 1 - C++

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.

Solution 2 - C++

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).

Solution 3 - C++

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.

Solution 4 - C++

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

Solution 5 - C++

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: https://stackoverflow.com/questions/41704561/does-specifying-the-use-of-void-in-the-declaration-of-a-function-that-takes-no-a

Solution 6 - C++

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSmacLView Question on Stackoverflow
Solution 1 - C++Chris YoungView Answer on Stackoverflow
Solution 2 - C++Zach HirschView Answer on Stackoverflow
Solution 3 - C++Dan OlsonView Answer on Stackoverflow
Solution 4 - C++Ciro Santilli Путлер Капут 六四事View Answer on Stackoverflow
Solution 5 - C++kmiklasView Answer on Stackoverflow
Solution 6 - C++MSaltersView Answer on Stackoverflow