为什么“函数名称”是在 C 中评估为 true 以及如何收到警告
我最近偶然发现 gcc 3.2.2 编写 ac 程序的以下行为:
在 if 语句中我忘记了函数的大括号并写道:
if(myFunc)...
而不是 if (myFunc())...
尽管我几乎打开了每个警告,但这并没有生成错误,也没有生成警告。
它只是评估为true
。 首先为什么要编写法律代码? 因为该函数存在/有一个地址? 有谁知道如何避免此类错误,或者是否有我忽略的警告选项?这个问题在以后的 gcc 版本中是否得到了更好的解决?
这里确切的编译器要求完整性:(
msp430-gcc -g -Os -mmcu=msp430x1611 -Wall -W -Wfloat-equal -Wundef -Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wwrite-strings -Wsign-compare -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations
-Wredundant-decls -Wnested-externs -Wimplicit-function-declaration -Werror
因为我被迫使用 gcc 3.2.3,所以没有 -Wextra)
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-compare -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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
if (myFunc)
相当于if (&myFunc)
,因此您正在测试函数的地址,该地址当然始终为非零,即真的。使用 gcc 4.2.1 和
-Wall
我收到以下警告:myfunc.c:11:警告:'myFunc' 的地址将始终评估为 'true'
if (myFunc)
is equivalent toif (&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
只是函数的内存地址,并且不为零。您的 if 语句与编写几乎相同:
作为非零值,它是
true
。没有警告似乎是合适的,因为测试函数指针以查看它们是否为 NULL 是有效的,甚至有些常见。
myFunc
is simply the memory address of the function, and is non-zero.Your if-statement is pretty much the same as writing:
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
,因为它的函数名称将始终评估为true
,因为它是一个指针。更具体地说,它必须是一个非空指针,因为您需要取消引用它。null
指针的计算结果为false
。简而言之,编译器似乎没有办法告诉你你犯了一个错误。
您需要做的是进行一些单元测试,分别调用
true
和false
响应,以便您可以知道您实际上已经调用了该函数。myFunc
, since its the name of a function will always evaluate totrue
because its a pointer. More specifically it has to be a non-null pointer because you will be needing to dereference it. Anull
pointer would evaluate tofalse
.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
andfalse
responses so that you can tell that you've actually called the function.指向函数的指针有时很有用 - 作为回调,例如在排序例程或数据捕获中。或者用于执行优化的计算转到类型例程,因为 C 没有模板。
但 99% 的情况下这是一个错误,较新的编译器会警告你
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
这是为了支持旧的链接器 hack;许多编译器/链接器(包括 gcc 和 GNU binutils)允许您为计算结果为 0 的函数定义弱符号,除非链接的另一个目标文件/共享库覆盖该符号的值。 glibc 利用这个技巧来进行一些版本兼容性攻击。
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.