Какова цель блока if (0) в блоке if-else?
Мой вопрос касается строки, которую я упомянул в теме, и которую я вижу во многих местах внутри производственного кода.
Общий код выглядит следующим образом:
if (0) {
// Empty braces
} else if (some_fn_call()) {
// actual code
} else if (some_other_fn_call()) {
// another actual code
...
} else {
// default case
}
Другие ветки не имеют отношения к моему вопросу. Мне интересно, что означает значение if (0)
здесь. Скобки пусты, поэтому я не думаю, что он должен комментировать некоторый блок кода. Заставляет ли это заставить компилятор сделать некоторую оптимизацию или разные ее намерения?
Я попытался найти этот явный случай здесь, на SO и в Интернете, но без успеха. Есть похожие вопросы о JavaScript, но не C. Там другой вопрос: что происходит, когда нуль присваивается в условии "если"? , но в нем обсуждается нулевое присвоение переменной, а не "if (0)".
Ответы
Ответ 1
Я иногда использую это для симметрии, поэтому я могу перемещать else if{
свободно с моим редактором, не имея в виду первое, if
.
Семантически
if (0) {
// Empty braces
} else
часть ничего не делает, и вы можете рассчитывать на оптимизаторы, чтобы удалить ее.
Ответ 2
Это может быть полезно, если существуют инструкции #if
, ala
if (0)
{
// Empty block
}
#if TEST1_ENABLED
else if (test1())
{
action1();
}
#endif
#if TEST2_ENABLED
else if (test2())
{
action2();
}
#endif
и т.п.
В этом случае любые (и все) тесты могут быть #if
' out, и код будет скомпилирован правильно. Почти все компиляторы будут удалять часть if (0) {}
. Простой автогенератор может генерировать такой код, так как он немного легче кодировать - ему не нужно рассматривать первый разрешенный блок отдельно.
Ответ 3
Я видел аналогичную модель, используемую в сгенерированном коде. Например, в SQL я видел, как библиотеки издавали следующее предложение where
.
where 1 = 1
Это, по-видимому, упрощает просто добавление по другим критериям, поскольку все дополнительные критерии могут быть добавлены and
вместо дополнительной проверки, чтобы убедиться, что это первый критерий или нет.
Ответ 4
Как написано, предложение if (0) {}
ничего не компилирует.
Я подозреваю, что функция предложения в верхней части этой лестницы - это простое место для временного отключения всех остальных функций сразу (для целей отладки или сравнения) путем изменения 0
на 1
или true
.
Ответ 5
Я не уверен в какой-либо оптимизации, но мои два цента:
Это произошло из-за некоторой модификации кода, где было удалено одно основное условие (например, вызов функции в начальном блоке, if
блок), но разработчики/сопровождающие
поэтому вместо удаления связанного if
блока они просто изменили условие на if(0)
и переместились дальше.
Ответ 6
Одна из возможностей, о которой еще не упоминалось: строка if (0) {
может быть удобной для точки останова.
Отладка часто выполняется на неоптимизированном коде, поэтому всегда будет ложный тест и он сможет установить на нем контрольную точку. При компиляции для производства линия кода будет оптимизирована. По-видимому, бесполезная строка дает функциональность для разработки и тестирования, не влияя на выпуск сборок.
Есть и другие хорошие предложения выше; единственный способ узнать, какова цель, - отследить автора и спросить. Система управления исходным кодом может помочь в этом. (Ищите функцию blame
-type.)
Ответ 7
Это код гниет.
В какой-то момент, что "если" сделал что-то полезное, ситуация изменилась, возможно, оцениваемая переменная была удалена.
Человек, который исправлял/менял систему, как можно меньше воздействовал на логику системы, поэтому он просто убедился, что код будет перекомпилирован. Поэтому он оставляет "if (0)", потому что это быстро и легко, и он не совсем уверен, что он хочет сделать. Он заставляет систему работать, и он не возвращается, чтобы исправить это полностью.
Затем появляется следующий разработчик и думает, что это было сделано намеренно и только комментирует эту часть кода (поскольку он не оценивается в любом случае), то в следующий раз, когда код коснется этих комментариев, удаляются.
Ответ 8
Я видел недопустимые блоки кода в предварительно расширенном JavaScript, которые были сгенерированы с использованием языка шаблонов.
Например, код, который вы читаете, может быть вставлен с сервера, который предварительно оценил первое условие, которое в то время полагалось на переменную, доступную только на стороне сервера.
if ( ${requestIsNotHttps} ){ ... }else if( ...
который когда-то предварительно скомпилировал людей:
if ( 0 ){ ... }else if ( ...
надеюсь, что это поможет вам релятивизировать потенциальную низкую активность клавиатуры в эпоху рецидивирующих кодеров, для которой я проявляю энтузиазм!
Ответ 9
Как было сказано, нуль оценивается как false, и ветвь, вероятно, будет оптимизирована компилятором.
Я также видел это раньше в коде, где была добавлена новая функция, и был необходим kill-switch (если что-то пошло не так с функцией, которую вы можете просто отключить), а некоторое время спустя, когда kill-switch был удален, программист также не удалял ветвь, например
if (feature_a_active()) {
use_feature_a();
} else if (some_fn()) {
...
стал
if (0) {
// empty
} else if (some_fn()) {
...
Ответ 10
Я думаю, что это просто плохой код. Написав быстрый пример в Compiler Explorer, мы видим, что в gcc и clang не генерируется код для блока if (0)
, даже если оптимизация полностью отключена:
https://godbolt.org/z/PETIks
Игра с удалением if (0)
вызывает изменений в сгенерированном коде, поэтому я делаю вывод, что это не оптимизация.
Возможно, что раньше было что-то сверху, if
блок был удален. Короче говоря, похоже, что удаление этого приведет к созданию того же самого кода, поэтому не стесняйтесь этого делать.
Ответ 11
Эта конструкция может также использоваться в C для реализации общего программирования с безопасностью типа, полагаясь на то, что компилятор все еще проверяет недостижимый код:
// this is a generic unsafe function, that will call fun(arg) at a later time
void defer(void *fun, void *arg);
// this is a macro that makes it safer, by checking the argument
// matches the function signature
#define DEFER(f, arg) \
if(0) f(arg); \ // never actually called, but compile-time checked
else defer(f, (void *)arg); // do the unsafe call after safety check
void myfunction(int *p);
DEFER(myfunction, 42); // compile error
int *b;
DEFER(myfunction, b); // compiles OK
Ответ 12
Это помогает отлаживать этот блок, просто помещая его в блок 1. Это отключает все функции if else block. А также мы можем расширить блок if else.
Ответ 13
Ответ @PSkocik в порядке, но я добавляю свои два цента. Не уверен, что я должен делать это как комментарий или как ответ; выбирая последнее, потому что ИМХО стоит того, что видят другие, тогда как комментарии часто невидимы.
Я не только иногда использую
if(0) {
//deliberately left empty
} else if( cond1 ) {
//deliberately left empty
} else if( cond2 ) {
//deliberately left empty
...
} else {
// no conditions matched
}
Но иногда я тоже
if( 1
&& cond1
&& cond2
...
&& condN
) {
или же
if( 0
|| cond1
|| cond2
...
&& condN
) {
для сложных условий. По тем же причинам - проще редактировать, #ifdef и т.д.
Если уж на то пошло, в Perl я сделаю
@array = (
elem1,
elem2,
...
elem1,
) {
- обратите внимание на запятую в конце списка. Я забываю, что запятые являются разделителями или разделителями в списках C и C++. ИМХО, это одно, чему мы научились: [ Являются ли запятые в Perl плохой практикой? запятые] - хорошая вещь. Как и любая новая нотация, требуется некоторое время, чтобы привыкнуть.
Я сравниваю код if(0)
с lisp
(cond (test1 action1)
(test2 action2)
...
(testn actionn))
который, как вы догадались, я могу отступать как
(cond
(test1 action1)
(test2 action2)
...
(testn actionn)
)
Иногда я пытался представить, что может выглядеть более понятный для пользователя синтаксис.
возможно
IF
:: cond1 THEN code1
:: cond2 THEN code2
...
:: condN THEN codeN
FI
вдохновленный Dikstra [ https://en.wikipedia.org/wiki/Guarded_Command_Language#Selection:_if][Guarded Command Language].
Но этот синтаксис подразумевает, что условия оцениваются параллельно, тогда как if...else-if
подразумевает последовательную и приоритетную оценку условий.
Я начал заниматься такими вещами при написании программ, которые генерировали другие программы, где это особенно удобно.
Хотя мы и находимся в этом, при написании RTL с использованием старого Intel iHDL, у меня есть кодированные материалы, такие как
IF 0 THEN /*nothing*/
**FORC i FROM 1 TO 10 DOC**
ELSE IF signal%i% THEN
// stuff to do if signal%i% is active
**ENDC**
ELSE
// nothing matched
ENDIF
где FORC..DOC..ENDC
представляет собой схему цикла макропроцессора, которая расширяется до
IF 0 THEN /*nothing*/
ELSE IF signal1 THEN
// stuff to do if signal1 is active
ELSE IF signal2 THEN
// stuff to do if signal2 is active
...
ELSE IF signal100 THEN
// stuff to do if signal100 is active
ELSE
// nothing matched
ENDIF
Это было одно назначение, не императивный код, поэтому установка переменной состояния не разрешалась, если вам нужно было делать такие вещи, как найти первый бит набора.
IF 0 THEN /*nothing*/
ELSE IF signal1 THEN
found := 1
ELSE IF signal2 THEN
found := 2
...
ELSE IF signal100 THEN
found := 100
ELSE
// nothing matched
ENDIF
Подумайте об этом, возможно, это первое место, где я столкнулся с такими конструкциями.
BTW, возражения, которые некоторые из них имели в стиле if (0), - что условия else-if последовательно зависят и не могут быть произвольно переупорядочены - не применяются к логике AND и OR и XOR в RTL, - но применимы к краткосрочным, circuit && и ||.
Ответ 14
Actually according to my opinion, if we put any variable for checking inside
e.g:-
public static void main(string args[])
{
var status;
var empList=_unitofWork.EmpRepository.Get(con=>con.isRetired==true);
//some code logic
if(empList.count>0)
{
status=true;
}
if(status)
{
//do something
}
else
{
//do something else
}
}
if then its dynamically get the value in run time and invoke the logic inside it, else its simply extra line of code i guess.
Anybody have any depth knowledge why this thing is used....or agree with me.
kindly respond.
Ответ 15
Я видел это несколько раз, я думаю, что наиболее вероятная причина заключается в том, что он оценивает что-то в старой/другой версии/ветки кода или, возможно, для отладки, и меняет его на if(0)
- несколько ленивый способ удалив все, что там было.