Почему «имя функции» оценивается как истинное в C и как получить предупреждение об этом - PullRequest
11 голосов
/ 01 декабря 2010

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

Ответы [ 5 ]

17 голосов
/ 01 декабря 2010

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

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

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

3 голосов
/ 01 декабря 2010

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

Ваше if-утверждение во многом аналогично написанию:

if (0x08451234) { ... }

А в качестве ненулевого значения оно равно true.

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

1 голос
/ 01 декабря 2010

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

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

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

0 голосов
/ 01 декабря 2010

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

0 голосов
/ 01 декабря 2010

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

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

...