views:

1070

answers:

4

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 a

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 a

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?

+30  A: 

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.

Chris Young
You beat me to it :)
Jason Coco
I did not know that void f() meant any number of parameters in C, thanks for pointing that out.
Daemin
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 parameters
Johannes Schaub - litb
Joe Pineda
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!
Dan Olson
+9  A: 

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

Zach Hirsch
Good point, thanks. But I think you should add it's bad practice in C, but not C++.
Chris Young
Yep, thanks. I've updated my answer.
Zach Hirsch
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.
Jonathan Leffler
A: 

In C++, int f(void) is indeed a deprecated declaration which is 100% equivalent to int f(). It is the same signature. The voidin 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.

MSalters
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)?
Chris Lutz
I've edited my answer to include the quote and citation.
Dan Olson
+5  A: 

The answers above 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).

Edit: After looking at the standard, 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.

Edit 2: Adding 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.

Dan Olson