11

我最近偶然发现了 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)

4

5 回答 5

17

if (myFunc)等价于if (&myFunc),因此您正在测试一个函数的地址,该地址当然总是非零,即为真。

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

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

于 2010-12-01T19:27:11.357 回答
3

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

您的 if 语句与编写几乎相同:

if (0x08451234) { ... }

作为一个非零值,它是true

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

于 2010-12-01T19:31:54.223 回答
1

myFunc,因为它是一个函数的名称,true因为它是一个指针。更具体地说,它必须是一个非空指针,因为您需要取消引用它。null指针将评估为false.

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

你需要做的是有一些单元测试分别调用truefalse响应,这样你就可以知道你实际上调用了这个函数。

于 2010-12-01T19:46:50.463 回答
0

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

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

于 2010-12-01T19:33:24.613 回答
0

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

于 2010-12-01T20:43:56.730 回答