为什么“a”;函数名";在C中计算为true以及如何得到警告

为什么“a”;函数名";在C中计算为true以及如何得到警告,c,gcc-warning,C,Gcc Warning,我最近无意中发现了gcc 3.2.2编写c程序的以下行为: 在if语句中,我忘记了函数的大括号,并写道: if(myFunc).而不是if(myFunc())… 虽然我已经打开了几乎所有的警告,但这并没有产生错误或警告 它的计算结果仅为true。 为什么要写法律法规呢? 因为函数存在/有地址? 有谁知道如何避免这样的错误,或者我是否忽略了一个警告选项?这个问题在以后的gcc版本中解决得更好吗 以下是编译器对完整性的确切要求: msp430-gcc -g -Os -mmcu=msp430x161

我最近无意中发现了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)

if(myFunc)
相当于
if(&myFunc)
,所以您正在测试函数的地址,当然它总是非零的,即true

根据gcc 4.2.1和
-Wall
,我得到以下警告:

myfunc.c:11:警告:“myfunc”的地址将始终计算为“true”

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

您的if语句与编写以下内容几乎相同:

if (0x08451234) { ... }
作为非零值,它是
true


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

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


但是99%的时候它是一个错误,较新的编译器会警告您,因为它的函数名总是计算为true,因为它是一个指针。更具体地说,它必须是非空指针,因为您将需要取消对它的引用。
null
指针的计算结果为
false

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


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

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

测试函数指针很常见。测试总是有非零地址的函数并不常见。我不确定函数指针和函数之间的编译代码有多大区别。它们都是可以通过jmp发送到的地址。阿贝伦基:有。一个是包含函数地址(并且可以重新分配)的内存位置,另一个是简单的文本地址。这类似于数组/指针的区别:函数名在函数指针适当的位置衰减为函数指针,但更清楚的是要保持语义上的区别,我认为这里最大的区别在于函数名永远不会为空。编译器可以清楚且容易地判断函数永远不会为零,但函数指针可能会在某个地方设置为NULL。只要定义了
myFunc
,这就保证为真,并且总是执行分支,因此如果存在
else
分支,您可能会看到一些死代码。这可能会引发一个警告。。。另外,我的
mangcc
说“-Wextra(这个选项过去被称为-W。旧名称仍然受支持,但新名称更具描述性。)”是
myFunc
函数还是函数指针?@Adam:myFunc()是普通名称function@dmckee:-W禁用gcc 3.2.3中的警告@Martin:Ah,翻译中的格式丢失;那是
-W.
。大概句号是国旗的一部分…我害怕这样的事情。你知道如何使用较旧的gcc版本(3.2.2)得到警告吗?@Martin:我所能建议的就是使用较新版本的gcc声明它将始终为非零?(不太可能/=总是。)@Conrad:很难说,但是如果你将测试更改为
if(myFunc!=NULL)
,那么gcc警告将更改为
myFunc.c:11:警告:“myFunc”的地址将永远不会为NULL
,这往往意味着函数地址永远不能为零(我知道不是权威的)。@Conrad:yes,每一个有效的指针都保证对一个空指针计算非相等值。这就是为什么没有警告的原因吗?