C99 quotes
This answer aims to quote and explain the relevant parts of the C99 N1256 standard draft.
Definition of declarator
The term declarator will come up a lot, so let's understand it.
From the language grammar, we find that the following underline characters are declarators:
int f(int x, int y);
^^^^^^^^^^^^^^^
int f(int x, int y) { return x + y; }
^^^^^^^^^^^^^^^
int f();
^^^
int f(x, y) int x; int y; { return x + y; }
^^^^^^^
Declarators are part of both function declarations and definitions.
There are 2 types of declarators:
- parameter type list
- identifier list
Parameter type list
Declarations look like:
int f(int x, int y);
Definitions look like:
int f(int x, int y) { return x + y; }
It is called parameter type list because we must give the type of each parameter.
Identifier list
Definitions look like:
int f(x, y)
int x;
int y;
{ return x + y; }
Declarations look like:
int g();
We cannot declare a function with a non-empty identifier list:
int g(x, y);
because 6.7.5.3 "Function declarators (including prototypes)" says:
3 An identifier list in a function declarator that is not part of a definition of that function shall be empty.
It is called identifier list because we only give the identifiers x
and y
on f(x, y)
, types come after.
This is an older method, and shouldn't be used anymore. 6.11.6 Function declarators says:
1 The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.
and the Introduction explains what is an obsolescent feature:
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.26]) is discouraged
f() vs f(void) for declarations
When you write just:
void f();
it is necessarily an identifier list declaration, because 6.7.5 "Declarators" says defines the grammar as:
direct-declarator:
[...]
direct-declarator ( parameter-type-list )
direct-declarator ( identifier-list_opt )
so only the identifier-list version can be empty because it is optional (_opt
).
direct-declarator
is the only grammar node that defines the parenthesis (...)
part of the declarator.
So how do we disambiguate and use the better parameter type list without parameters? 6.7.5.3 Function declarators (including prototypes) says:
10 The special case of an unnamed parameter of type void as the only item in the list specifies that the function has no parameters.
So:
void f(void);
is the way.
This is a magic syntax explicitly allowed, since we cannot use a void
type argument in any other way:
void f(void v);
void f(int i, void);
void f(void, int);
What can happen if I use an f() declaration?
Maybe the code will compile just fine: 6.7.5.3 Function declarators (including prototypes):
14 The empty list in a function declarator that is not part of a
definition of that function specifies that no information about the number or types of the
parameters is supplied.
So you can get away with:
void f();
void f(int x) {}
Other times, UB can creep up (and if you are lucky the compiler will tell you), and you will have a hard time figuring out why:
void f();
void f(float x) {}
See: Why does an empty declaration work for definitions with int arguments but not for float arguments?
f() and f(void) for definitions
f() {}
vs
f(void) {}
are similar, but not identical.
6.7.5.3 Function declarators (including prototypes) says:
14 An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters.
which looks similar to the description of f(void)
.
But still... it seems that:
int f() { return 0; }
int main(void) { f(1); }
is conforming undefined behavior, while:
int f(void) { return 0; }
int main(void) { f(1); }
is non conforming as discussed at: Why does gcc allow arguments to be passed to a function defined to be with no arguments?
TODO understand exactly why. Has to do with being a prototype or not. Define prototype.