为什么“函数名称”在C中评估为true,以及如何在其上发出警告

时间:2010-12-01 19:24:57

标签: c gcc-warning

我最近偶然发现了gcc 3.2.2编写c程序的以下行为:

在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)

5 个答案:

答案 0 :(得分:17)

if (myFunc)等同于if (&myFunc),因此您正在测试函数的地址,当然这将始终为非零,即为真。

使用gcc 4.2.1和-Wall我收到以下警告:

myfunc.c:11: warning: the address of ‘myFunc’ will always evaluate as ‘true’

答案 1 :(得分:3)

myFunc只是函数的内存地址,并且不为零。

你的if语句与写作几乎相同:

if (0x08451234) { ... }

作为非零值,它是true

没有警告似乎是合适的,因为测试函数指针是否有效甚至有些常见,以确定它们是否为NULL。

答案 2 :(得分:1)

myFunc,因为它的函数名称总是会计算为true,因为它是一个指针。更具体地说,是一个非空指针,因为你需要取消引用它。 null指针将评估为false

简而言之,编译器似乎没有办法告诉你你犯了错误。

您需要做的是让一些单元测试单独调用truefalse响应,以便您可以告诉您实际上已经调用了该函数。

答案 3 :(得分:0)

指向函数的指针有时很有用 - 例如在排序例程或数据捕获中作为回调。或者为了进行优化的计算goto类型例程,因为C没有模板。

但99%的情况下,这是一个错误,较新的编译器会警告你

答案 4 :(得分:0)

这是为了支持一个旧的链接器hack;许多编译器/链接器(包括gcc和GNU binutils)允许您为函数定义弱符号,该函数的计算结果为0,除非另一个链接的目标文件/共享库覆盖符号的值。 glibc利用这个技巧来解决一些版本兼容问题。