我最近偶然发现了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)
答案 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
。
简而言之,编译器似乎没有办法告诉你你犯了错误。
您需要做的是让一些单元测试单独调用true
和false
响应,以便您可以告诉您实际上已经调用了该函数。
答案 3 :(得分:0)
指向函数的指针有时很有用 - 例如在排序例程或数据捕获中作为回调。或者为了进行优化的计算goto类型例程,因为C没有模板。
但99%的情况下,这是一个错误,较新的编译器会警告你
答案 4 :(得分:0)
这是为了支持一个旧的链接器hack;许多编译器/链接器(包括gcc和GNU binutils)允许您为函数定义弱符号,该函数的计算结果为0,除非另一个链接的目标文件/共享库覆盖符号的值。 glibc利用这个技巧来解决一些版本兼容问题。