Почему "имя функции" оценивается как true на C и как его предупреждать

Недавно я наткнулся на следующее поведение 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)

Ответ 1

if (myFunc) эквивалентен if (&myFunc), поэтому вы проверяете адрес функции, который, конечно, всегда будет отличным от нуля, т.е. true.

С gcc 4.2.1 и -Wall я получаю следующее предупреждение:

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

Ответ 2

myFunc - это просто адрес памяти функции и не равен нулю.

Ваш оператор if почти такой же, как и запись:

if (0x08451234) { ... }

И как ненулевое значение, это true.

Никакое предупреждение не представляется подходящим, поскольку оно действительно и даже несколько обычное для проверки указателей функций, чтобы увидеть, являются ли они NULL или нет.

Ответ 3

myFunc, так как его имя функции всегда будет оцениваться как true, потому что его указатель. Более конкретно, это должен быть ненулевой указатель, потому что вам нужно будет разыменовать его. Указатель null будет оценивать значение false.

Короче говоря, похоже, что компилятор не может сказать вам, что вы допустили ошибку.

Что вам нужно сделать, это иметь некоторые модульные тесты, которые отдельно вызывают ответы true и false, чтобы вы могли сказать, что вы действительно вызвали эту функцию.

Ответ 4

Указатели на функции иногда полезны - как обратные вызовы, например, в процедурах сортировки или сборе данных. Или для выполнения оптимизированных подпрограмм типа calc-goto, поскольку C не имеет шаблонов.

Но в 99% случаев это ошибка, новые компиляторы будут предупреждать вас

Ответ 5

Это поддержка старого взлома компоновщика; многие компиляторы/компоновщики (в том числе gcc и GNU binutils) позволяют вам определить слабый символ для функции, которая оценивает значение 0, если только связанная с ним связанная ссылка на объектный файл/разделяемую библиотеку не переопределяет значение символа. glibc использует этот трюк для некоторых версий совместимости версий.