2013-04-25 2 views
22

Просмотр среди некоторых унаследованного кода я нашел такую ​​функцию:Зачем использовать 'function address == NULL' вместо 'false'?

static inline bool EmptyFunc() 
{ 
    return (void*) EmptyFunc == NULL; 
} 

Какие отличия от этого:

static inline bool EmptyFunc() 
{ 
    return false; 
} 

Этот код был создан для компиляции под несколькими различными платформами, как PS2, Wii, PC ... Есть ли какая-то причина для использования первой функции? Как лучше оптимизировать или избежать какого-то странного неправильного поведения компилятора?

+4

Я думаю, что это потому, что если вы только что вернули «ложь», компилятор мог бы свободно оптимизировать эту функцию ... но тогда в любом месте, которое на самом деле использовало его, следует предотвратить такую ​​же оптимизацию. Хм. Где используется 'EmptyFunc'? Кроме того, почему приведение в 'void *'? Это не имеет смысла для указателей на функции ... – Cameron

+6

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

+2

'EmptyFunc' использовался как обратный вызов в процедуре регистрации пользовательских входных данных, которая проходила бы каждый зарегистрированный обратный вызов и отмечала бы соответствующее событие как вызванное, когда данный обратный вызов возвращает true. –

ответ

10

Семантически обе функции одинаковы: они всегда возвращают false *. Складывание первого выражения в постоянное значение «false» полностью разрешено стандартом, так как оно не изменит никаких наблюдаемых побочных эффектов (которых их нет). Поскольку компилятор видит всю функцию, он также может оптимизировать любые вызовы и заменить его на постоянное «ложное» значение.

Т.е. в первой форме нет «общего» значения и, вероятно, это ошибка со стороны программиста. Единственная возможность заключается в том, что он использует какое-то особое поведение (или дефект) в конкретном компиляторе/версии. В конце концов, я не знаю. Если вы хотите предотвратить встраивание с использованием атрибута, специфичного для компилятора, это правильный подход - все, что угодно, подвержено взлому, если компилятор изменится.

(* Предполагается, что NULL никогда не определяется как EmptyFunc, что приведет к возврату true).

+1

+1 Это тоже мое чувство, что это касается проблемы с компилятором (я видел худшие обходные пути для багги-компиляторов, но * как минимум * код был документирован, в отличие от здесь!). – syam

3

Строго говоря, указатель функции не может быть передан указателю на пустоту, что происходит тогда, выходя за рамки стандарта. Стандарт C11 перечисляет его как «общее расширение» в J.5.7 (я подозреваю, что то же самое относится к C++). Поэтому единственная разница между двумя случаями в том, что первая не переносима.

Казалось бы, наиболее вероятной причиной прежней версии является запутанный программист или запутанный компилятор. Мы можем точно сказать, что программист был смущен/неряшлив из-за отсутствия объясняющего комментария.

На самом деле не имеет смысла объявлять функцию как inline, а затем попытаться обмануть компилятор, не вставляя код, включив в него код функции. Поэтому я думаю, что мы можем исключить эту теорию, если, конечно, программист не смутился и не подумал, что это имеет смысл.

Смежные вопросы