Is f(void) deprecated in modern C and C++? [duplicate]
Asked Answered
V

6

68

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?

Vyatka answered 6/1, 2009 at 12:34 Comment(7)
Be careful not to lump C and C++ too closely together like this. There are differences that need to be taken into consideration...Margeret
I'm realising this more as I read the posts below. The refactor is to C++ in this case and dropping some C compatibility or style is not an issue.Vyatka
Dup: #7412774Scoundrel
@Will, dup question asked 2 years later ;)Vyatka
@Shane: I can see through time! The other answer has better detail. :)Scoundrel
If the C++ standards had required the void in the signature, then I believe they could have avoided the Most Vexing Parse.Polite
@Ciro, similar question but not the same, in that I'm asking whether or not one version is deprecated and a candidate for refactoring, and if so is it liable to lead to possible signature clash problems when working with other code, including statically linked libraries.Vyatka
B
101

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.

Buchner answered 6/1, 2009 at 12:37 Comment(5)
I did not know that void f() meant any number of parameters in C, thanks for pointing that out.Colorblind
i wouldn't word it with "takes any number of parameters", because it means "takes an unknown number of parameters of unknown types". giving it the wrong number results in undefined behavior. "..." means that it takes any numbers of additional parametersTopazolite
As far as I know, that syntax is not deprecated (Stroustrup himself said "every program in the K&R book is also a valid C++ program" but (as others point out), considered a C-ism. I prefer to use it to explicitly say a function takes no arguments. It also helps if you need to share code with C.Gorey
You're right, Joe, it's not deprecated syntax in C++. I checked the standard myself earlier. But funny enough, the empty parameter list has been deprecated syntax in C since 1989!Nereen
+1 When coding C code for safety applications (automotive, aerospace, etc.) strict coding guidelines (e.g. MISRA for automotive) must be followed and one is that you need to write f(void) and not f(). This is indeed because of the reasons stated by this answer.Vercelli
E
21

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

Eastnortheast answered 6/1, 2009 at 12:43 Comment(2)
Good point, thanks. But I think you should add it's bad practice in C, but not C++.Buchner
I am not convinced you need the "in my experience" qualifier; it is pretty much unreservedly bad practice. The only time it would be acceptable is if the C compiler is a pre-C89 compiler that does not accept function prototypes; they are rare indeed these days.Mylo
N
18

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.

Nereen answered 28/2, 2009 at 3:25 Comment(0)
N
2

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://mcmap.net/q/14687/-is-it-better-to-use-c-void-arguments-quot-void-foo-void-quot-or-not-quot-void-foo-quot-duplicate

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://mcmap.net/q/107551/-is-there-a-difference-between-foo-void-and-foo-in-c-or-c

Neapolitan answered 25/4, 2016 at 8:36 Comment(0)
B
2

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?

Bunche answered 17/1, 2017 at 18:0 Comment(0)
F
-1

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.

Fivefinger answered 6/1, 2009 at 12:50 Comment(2)
The answer above this says that f(void) is NOT deprecated. Will someone provide a link to or quote from the standard that talks about the deprecation (or lack thereof) of f(void)?Launcher
I've edited my answer to include the quote and citation.Nereen

© 2022 - 2024 — McMap. All rights reserved.