[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: functions with empty parameter lists
|
From: |
Bruno Haible |
|
Subject: |
Re: functions with empty parameter lists |
|
Date: |
Mon, 06 Feb 2023 23:48:08 +0100 |
Paul Eggert wrote:
> static void
> -init_sh_quoting_options ()
> +init_sh_quoting_options (void)
> {
Your change prompted me to wonder whether this patch should be generalized,
that is, whether all function definitions with empty parameter lists should
be changed to use this style. Like in the attached patch.
I got doubts because
* I'm using the style with () in function definitions in many places, and
neither 'gcc -Wall' nor 'clang -Wall' has warned about it, in many years.
* The ISO C committee attempts to align C with C++ (e.g. regarding the
attributes syntax), and in C++ a function declaration or definition with
() denotes zero arguments.
There were two essential changes in this area in ISO C 23:
* https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2432.pdf
1) removed the K&R C syntax for function definitions
int foo (x, y) int x; long y; { ... }
2) in function definitions, () is equivalent to (void).
* https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2841.htm
3) A function declarator with a parameter list of () declares a prototype
for a function that takes no parameters (like it does in C++).
See ISO C 23 ยง 6.7.6.3.(13).
For those of us that are not standards experts, the effects can be seen
through two test cases, with clang 15.0.6.
=================================== foo1.c ===================================
#include <stdio.h>
void func();
int main() {
func("AAA");
return 0;
}
void func() {
printf("in func()\n");
}
=================================== foo2.c ===================================
#include <stdio.h>
void func() {
printf("in func()\n");
}
int main() {
func("AAA");
return 0;
}
==============================================================================
clang diagnostics for older standard versions:
$ clang -Wall foo1.c
foo1.c:6:9: warning: passing arguments to 'func' without a prototype is
deprecated in all versions of C and is not supported in C2x
[-Wdeprecated-non-prototype]
func("AAA");
^
1 warning generated.
$ clang -Wall foo2.c
foo2.c:8:15: warning: too many arguments in call to 'func'
func("AAA");
~~~~ ^
foo2.c:8:9: warning: passing arguments to 'func' without a prototype is
deprecated in all versions of C and is not supported in C2x
[-Wdeprecated-non-prototype]
func("AAA");
^
2 warnings generated.
clang diagnostics for C23:
$ clang -std=gnu2x -Wall foo1.c
foo1.c:6:10: error: too many arguments to function call, expected 0, have 1
func("AAA");
~~~~ ^~~~~
foo1.c:3:6: note: 'func' declared here
void func();
^
1 error generated.
$ clang -std=gnu2x -Wall foo2.c
foo2.c:8:10: error: too many arguments to function call, expected 0, have 1
func("AAA");
~~~~ ^~~~~
foo2.c:3:6: note: 'func' declared here
void func() {
^
1 error generated.
What does this mean?
(I) In function *definitions*, () and (void) mean the same: zero arguments.
This was always the case, in C89, in K&R C, and equally in C++.
(II) Regarding function *declarations*, this gives a whole new view of the
history.
* In C23, () and (void) mean the same: zero arguments. It's like this
in C++ as well, for many years.
* The (void) syntax was only introduced as a temporary workaround,
as long as - in C only, not in C++ - () in function declarations meant
a varargs list: (...).
* The GCC warning -Wstrict-prototypes is a migration aid, whose purpose
is to remind the programmer to convert declarations such as
void func ();
to either
void func (void);
or
void func (first_t arg, ...);
Unfortunately, this GCC warning also warns about function definitions
void func () { ... }
although there was never a need to warn about these; see (I) above.
(III) So, why is (void) allowed in function *definitions* at all?
I can only guess:
- Maybe the future standardization path of this area was not clear
in 1989. (For instance, C++ did not exist at that time, and nowadays
ISO C is following ISO C++ in some aspects.)
- There was the desire to have the same syntax across function
declarations/types and function definitions.
Now, how should we go ahead in this situation? This is my opinion:
* In the long term, assuming ISO C 23 and newer, writing (void) is just
clutter in those places where one can just as well write (). The keyword
'void' here only tells that the programmer has accomplished the migration
from K&R C to ISO C 23, nothing else.
* We can assume that the readers and contributors of our code know the
difference between a function declaration/type and a function definition.
Therefore, I'm in favour of turning all (void) in function *definitions*
to ().
This can happen now or any time.
* We should stop compiling with -Wstrict-prototypes and instead (not always,
but frequently enough) compile with the '-std=gnu23' option. Clang
currently implements it better. GCC 13 may be on par with clang again on
this topic [1].
* We need to continue to use (void) in function declarations/types, as long
as we support compilers for ISO C standards before C 23. This will
probably take 10 or 15 years.
Bruno
[1] https://gcc.gnu.org/gcc-13/changes.html
use-void-parameter-lists-in-function-definitions.diff
Description: Text Data