У меня есть программа. Где-то в программе у меня есть этот код:
int
read_n(char *cp, int n)
{
int nread;
if ((nread = read(STDIN_FILENO, cp, n)) != n)
if (nread == -1)
die(DIE_ERROR_FMT, "failed reading input");
else
return nread;
return n;
}
и скомпилировать мою программу следующим образом:
cc -std=c99 -Wall -Wextra -Wshadow -Wpedantic prog.c -o prog
Я получил:
le.c:343:5: warning: add explicit braces to avoid dangling else [-Wdangling-else]
Почему именно это предупреждение и необходимо? Я знаю, что else
идет к ближайшему else
-менее if
, и предпочитаю по возможности избегать фигурных скобок (для удобочитаемости). Это clang
, gcc
выдает аналогичную ошибку.
добавь -Wno-dangling-else
.
Смотрите , почему опускать фигурные скобки считается плохой практикой?
это может ввести в заблуждение и сбить с толку, если отступы в коде сделаны по-другому.
@StanislavVolodarskiy Это должен быть ответ.
@pmacfarlane: избегание фигурных скобок не является серьезной ошибкой. Это один из инструментов для уменьшения ошибок. Он имеет положительные и отрицательные стороны. Есть и другие инструменты, тоже с плюсами и минусами. Какие инструменты использовать – это выбор.
@EricPostpischil Я не имел в виду ошибку как ошибку. Очевидно, что это действительно так. Но хорошо известно, что он хрупкий и запутанный — он никогда не пройдет проверку кода в любом месте, где я когда-либо работал.
@pmacfarlane: Это ваше мнение и выбор места работы. Это не универсально и не факт. Однострочный оператор с if
не сбивает с толку.
Одна строка, содержащая макрос, может быть ошибкой, а может и не быть.
Почему «dangling-else» выдает предупреждение?
Потому что иногда такой код пишется по ошибке:
if (A)
if (B)
C;
else // Intended to apply to A but applies to B.
D;
Компилятор распознает шаблон и не может быть уверен, есть ли ошибка, поэтому он предупреждает вас.
Это вряд ли произойдет в простом коде, но учтите:
if (A)
if (B)
{
Several dozen lines of code…
}
В этом случае человек, который позже добавляет else
, намереваясь использовать его для A
, может не увидеть промежуточный if
вместо B
, когда он добавляет else
. Это может быть прокручено из окна их редактора. Итак, когда компилятор видит этот шаблон и включено предупреждение dangling-else
, он предупреждает вас.
(Было бы неплохо, если бы компилятор учитывал отступы и, если отступы были постоянными во всей программе, а отступы else
соответствовали его совпадениям if
, не выдавал это предупреждение.)
«Было бы неплохо, если бы компилятор учитывал отступы и, если отступы были одинаковыми во всей программе, а отступы else соответствовали их совпадениям, если бы он не выдавал это предупреждение». - нет, с тем, насколько распространены автоформатеры и автоматические отступы, слишком часто висячие elses просто автоматически выравниваются по if
, которым они соответствуют, а не по if
, которым они должны были соответствовать. Вы не можете доверять отступу, чтобы он соответствовал намерению.
@ user2357112: автоматический отступ также помогает пользователям раньше обнаруживать ошибки и обеспечивать соответствие написанного кода предполагаемому коду. Добавление фигурных скобок создает беспорядок, который в некоторых случаях приводит к ошибкам.
Конечно, автоматический отступ полезен. Я просто говорю, что, поскольку согласованный отступ так часто происходит автоматически, это не лучший индикатор того, что висячие elses соответствуют тому, с чем они должны были совпадать.
@user2357112: user2357112: Но предупреждение компилятора о зависании-иначе раздражает некоторых людей, поэтому они его не используют. Неиспользованный инструмент не имеет ценности. Улучшение его с учетом отступов может уменьшить неудобства и сделать его достойным использования.
Я не совсем понимаю вашу точку зрения @ user2357112. Для меня автоматический отступ часто позволяет мне узнать, на какой if
в этом примере идет else
, и я могу уловить это таким образом.
Я ненавижу идею компилятора, даже знающего об отступах. Со всем этим должны справиться препроцессор и лексер. Пробел не имеет значения в C
, и мне это нравится.
@ user129393192: Да, здесь может помочь автоматический отступ. Автоматический отступ полезен! Но если бы висячие else-предупреждения работали так, как предлагает Эрик, то автоматический отступ эффективно отключил бы висячие else-предупреждения. Компилятор предположил бы, что каждый else
соответствует if
, которому он должен соответствовать, основываясь на отступе, который был написан инструментом, а не человеком, который написал оборванный else
.
Я понимаю. Я не уверен, что вы используете, но я использую eMac и активно вижу автоматический отступ в игре и сам проверяю его @ user2357112
@pmacfarlane, тогда ты должен ненавидеть Python. Но я предпочитаю отступ фигурным скобкам, и любой здравомыслящий человек в любом случае хорошо сделает отступ, даже если он не имеет синтаксического значения.
OP заявляет: «и предпочитаю избегать фигурных скобок, когда это возможно (для удобочитаемости)»
Это приводит к изучению потока представленного кода. Для удобочитаемости этот поток можно было бы выразить без обращения к else
, оборванному или нет:
int
read_n(char *cp, int n)
{
int nread = read(STDIN_FILENO, cp, n); // simply expressed (ie. not nested in an 'if')
if (nread == n) // desired result
return n;
if (nread != -1) // suboptimal result, but not total failure
return nread;
// react to complete failure
die(DIE_ERROR_FMT, "failed reading input");
return -1; // or is execution already stopped?
}
Немного комментариев и простая логика облегчают понимание этой процедуры. Это обходит вопрос о любых болтающихся еще.
Ваш ответ мне очень помог. Код теперь int read_n(char *cp, int n) { int nread = read(STDIN_FILENO, cp, n); if (nread != -1) return nread; else die(DIE_ERROR_FMT, "failed reading input"); }
.
Отступы не имеют значения в C. Каждое из следующего в точности идентично:
if a()
if b()
foo()
else
bar()
и
if (a)
if (b)
foo()
else
bar()
и
if (a)
if (b)
foo()
else
bar()
Компилятор предупреждает вас, что людям это кажется двусмысленным, и вы должны явно добавить фигурные скобки, чтобы ваш код был очевиден.
Приняли, потому что оно было самым прямым и ясным. Вы специально указали, что отступ не имеет значения в C, и поэтому компилятор делает это. Спасибо. Вы разъяснили мне это.
Избегать фигурных скобок (для удобочитаемости??) — большая ошибка. Всегда используйте фигурные скобки, если только это не очень простой оператор
if
безelse
.