So I found a
bug (it's
probably shouldn't really be "important" but I do include a fix). I know
why this bug happens, undefined functions are assumed to return an int,
so it chops off the top of a 64 bit pointer.
but why? delving into the standards is tricky. first some terms
a function declaration gives the function name and the paramaters.
It has a return type, a name and a paramater list. Each of the
paramaters is possibly named (C99 6.7.5.3.6 : ...specifies the types
of, and may declare identifiers for, the parameters of the function
and later, C99 6.9.1 : If the declarator includes a parameter type
list, the declaration of each parameter shall include an
identifier). It looks like
int afunction(int aparamater)
.
a function prototype is like a weak version of a function
declaration. It specifies the return value and the paramaters, but
doesn't give the paramater names (C99 6.2.1 : A function prototype
is a declaration of a function that declares the types of its
parameters). This is used for C++ compatability, I think. It looks
like
int afunction(int)
So you can say a function prototype is always a function declaration,
but a function declaration isn't always a prototype.
a function definition is where you actually write the function. It
looks like
int afunction(int aparamater) { return aparamater; }
Note that a function definition is also a declaration, which is why
you can happily use functions after they are defined in the source
code.
Ian Lance Taylor
suggested the
relevant part of the C99 standard dealing with undefined functions says
6.5.2.2; Paragraph 1 : The expression that denotes the called
function shall have type pointer to function returning void or
returning an object type other than an array type.
The disallows undefined functions by omission; they're not mentioned so
they're not allowed. Actually, a little earlier when defining exactly
what an expression is (6.5.1.2) we get one definition of a primary
expression
An identifier is a primary expression, provided it has been declared
as designating an object (in which case it is an lvalue) or a
function (in which case it is a function designator)76
76: thus, an undeclared identifier is a violation of the syntax.
An undeclared identifier is not considered a primary expression. What's
an expression? Think of it as anything that can go to the right hand
side of an = or as the conditional of an if( ) statement.
So, a function declaration is just another type of declarator (C99
6.5.7) which declares an identifier which is the function name (e.g. in
the same way int i declares i as being an identifier of integer
type, int function(void) declares function() as an identifier of
a function that returns int taking no arguments).
Ian Lance Taylor goes on to
say
Given traditional C usage, requiring a function declaration can be
reasonably viewed as a pedantic requirement, appropriate for
-pedantic-errors. In general, if you want gcc to enforce strict
adherence to the relevant standard, you must use -pedantic-errors.
Of course there is a very reasonable coding style in which functions
should always be declared for use. For that coding style, there is
-Werror-implicit-function-declaration.
The only problem with this is that no one ever actually turns on those
flags, and on 32 bit system (which most of the world use) it doesn't
cause an error because the pointer is the same size as an int.