Почему "имя функции" оценивается как 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 использует этот трюк для некоторых версий совместимости версий.