Why does a "function name" evaluate to true in C and how to get warned on it
I recently stumbled across the following behaviour of gcc 3.2.2 writing a c program:
In an if statement I forgot the braces of a function and wrote:
if(myFunc)...
instead of if(myFunc())...
This did not generate an error neither a warning although I have pretty much every warning turned on.
It simply evaluated to true
.
Why is this writing legal code in the first place ?
Because the function exists/has an address ?
Does anyone know how one could avoid such mistakes or if there is a warning option I overlooked ? Is this issue better solved in later gcc versions ?
Here the exact compiler call for completeness:
msp430-gcc -g -Os -mmcu=msp430x1611 -Wall -W -Wfloat-equal -Wundef -Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wwrite-strings -Wsign-com开发者_开发百科pare -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations
-Wredundant-decls -Wnested-externs -Wimplicit-function-declaration -Werror
(Since I'm forced to use gcc 3.2.3 there is no -Wextra)
if (myFunc)
is equivalent to if (&myFunc)
, so you're testing the address of a function, which of course will always be non-zero, i.e. true.
With gcc 4.2.1 and -Wall
I get the following warning:
myfunc.c:11: warning: the address of ‘myFunc’ will always evaluate as ‘true’
myFunc
is simply the memory address of the function, and is non-zero.
Your if-statement is pretty much the same as writing:
if (0x08451234) { ... }
And as a non-zero value, it is true
.
No warning seems appropriate, as it is valid and even somewhat common to test function-pointers to see if they are NULL or not.
myFunc
, since its the name of a function will always evaluate to true
because its a pointer. More specifically it has to be a non-null pointer because you will be needing to dereference it. A null
pointer would evaluate to false
.
In short, there does not seem to be a way for the compiler to tell you that you've made a mistake.
What you need to do is to have some unit tests that separately invoke the true
and false
responses so that you can tell that you've actually called the function.
Pointers to functions are sometimes useful - as callbacks eg in sort routines or data capture. Or for doing optimized calculated-goto type routines, since C doesn't have templates.
But 99% of the time it's an error, newer compilers will warn you
This is to support an old linker hack; many compilers/linkers (including gcc and GNU binutils) allow you to define a weak symbol for a function which evaluates to 0 unless another object file/shared library that got linked overrides the value of the symbol. glibc makes use of this trick for some version-compatibility hacks.
精彩评论