Операторы условного возврата C/C++ [дубликаты]

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

foo() {
   if (a < b) {
       return 0;  // bail, since condition is met
   } else {
       // lots of calculations in this block
   }
   return 1;
}

Мой вопрос: плохо ли иметь несколько операторов возврата? Это плохая практика? Есть ли лучшие методы? MISRA что-нибудь говорит об этом?

ПРИМЕЧАНИЕ. Этот вопрос относится к встраиваемым системам и имеет отношение к MISRA, а не только к C/C++.

Спасибо...


person user1135541    schedule 18.06.2013    source источник
comment
Нет, это определенно не плохая практика.   -  person chris    schedule 18.06.2013
comment
Я бы также дошел до удаления else. Это необязательно.   -  person Joe Frambach    schedule 18.06.2013
comment
По ощущениям, это было бы лучше на программистах.SE.   -  person ardent    schedule 18.06.2013
comment
как только вы узнаете, что лучше не злоупотреблять, используйте его по мере необходимости   -  person Luca Rocchi    schedule 18.06.2013
comment
+1 за конкретный вопрос о MISRA, который, кажется, отличает его от типичного, каково ваше мнение? вопрос.   -  person Adrian McCarthy    schedule 19.06.2013
comment
Между прочим, эту функцию можно было бы записать и как bool foo (void) { return a >= b; }, оставаясь совершенно понятной и совместимой с MISRA.   -  person Lundin    schedule 19.06.2013
comment
@Lundin: Но тогда lots of calculations in this block не происходит.   -  person Bill    schedule 19.06.2013
comment
@JoeFrambach: +1, так как это одна из моих основных причин использовать множественный возврат: уменьшить глубину кода.   -  person eckes    schedule 19.06.2013
comment
@Bill Я не предлагал оптимизацию, я предложил улучшить читаемость, что также удовлетворило бы MISRA.   -  person Lundin    schedule 19.06.2013
comment
@Lundin: вы предложили преобразование, которое меняет семантику функции. Вместо того, чтобы делать много вещей, если a >= b, а затем возвращаться, вы просто return.   -  person Bill    schedule 19.06.2013


Ответы (5)


MISRA требует одного оператора возврата:

(MISRA, правило 14.7: требуется) «Функция должна иметь единую точку выхода в конце функции»

Лично я не думаю, что это хорошее правило. Сведите к минимуму количество операторов return, но используйте оператор return, если он повышает читабельность вашего кода.

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

Я предлагаю вам прочитать эту статью о дуффинге (написание кода сверху вниз):

person ouah    schedule 18.06.2013
comment
В этом предложении должна быть запятая между exit и at. В противном случае, ну, конечно, вы можете иметь только один оператор в конце функции! - person Joe Frambach; 18.06.2013
comment
Правило MISRA — ужасное правило. Особенно в C++, где вы можете просто return положиться на RAII. - person Massa; 18.06.2013
comment
+1 за на удивление хорошую дурацкую статью - person sehe; 18.06.2013
comment
Мне не понравилась эта дурацкая статья, поскольку она представляет соломенный код как единственную альтернативу продвигаемому стилю. Существуют и другие способы структурирования большинства этих примеров, которые (я полагаю) даже более удобочитаемы, тестируемы и удобны в сопровождении, чем те, которые поддерживаются. - person Adrian McCarthy; 19.06.2013
comment
@Massa MISRA не использовал свои собственные мозги, они просто цитировали IEC 61508, ошибочно полагая, что это стандарт, написанный здравомыслящими людьми. Смотрите мой комментарий к вопросу об источниках. Я даже указал на это комитету во время публичного рассмотрения MISRA-C12, но они предпочли по-прежнему избегать каких-либо обоснований своих правил. - person Lundin; 19.06.2013
comment
MISRA C:2012 изменил правило на «рекомендательный», и я поддерживаю утверждение, что правило правильно в большинстве случаев. Однако бывают ситуации, когда соблюдение этого правила делает вещи менее читабельными/поддерживаемыми, чем несоблюдение. - person Andrew; 24.07.2013
comment
@Lundin делает несправедливый комментарий о комитете MISRA (обратите внимание на заявление в моем профиле) и, в частности, в отношении IEC61508. Нравится ему (ей) это или нет, но 61508 цитируется в директивах ЕС и других юридических материалах, поэтому соответствие имеет значение, - person Andrew; 24.07.2013
comment
@ Эндрю Я должен был уточнить цитату из MISRA-C: 2004. Я не знал, что в то время был выпущен MISRA-C:2012. Спасибо за информацию. - person ouah; 24.07.2013
comment
@Andrew В какой именно директиве ЕС IEC 61508 указан в качестве нормативного стандарта? Что касается фактического научного источника, стоящего за этим, вы идете MISRA-C, который цитирует IEC61508, который цитирует (IEC 61508:7 C.2.9) один-единственный, полностью устаревший источник для этого убеждения: книга по программированию 34-летней давности. Нравится вам это или нет, но этот пережиток информатики является единственным обоснованием 61508, и, таким образом, MISRA обеспечивает. Так что я поддерживаю комментарий, не использующий собственные мозги. - person Lundin; 06.08.2013
comment
Начнем с Европейской директивы по машинному оборудованию 2006/42/EC, которая предписывает анализ опасностей и оценку рисков, которые должны быть выполнены и задокументированы OEM-производителем транспортного средства в соответствии со стандартом ISO 13849 (или другим стандартом функциональной безопасности в соответствии с требованиями национального законодательства). ISO 13849 относится к IEC-61508. - person Andrew; 07.08.2013
comment
@Andrew Вы можете реализовать продукт в соответствии со стандартами ISO 12100 и 13849-1 без использования IEC 61508, он просто указан в качестве ссылки в последнем. 61508 не является гармонизированным стандартом директивы по машинному оборудованию. См. EU 2013/C 99/01. В любом случае, несмотря на утверждения ISO, 13849-1 совершенно не подходит для использования в качестве руководства по безопасной разработке программного обеспечения. Где 61508 сомнительно, 13849 смешно. Любой программист должен прочитать, например, Приложение J4 для хорошего смеха / ностальгии по 70-м годам. - person Lundin; 08.08.2013
comment
@Lundin - я не согласен с вами ... вы можете да, но это требует понимания от специалистов по закупкам. И я долго и упорно доказывал, что 26262 не упоминается в MISRA C, и подвергал сомнению ссылки на 61508... но я был в меньшинстве, что, вероятно, было неизбежно, когда ведущие сторонники 26262 являются частью MISRA... - person Andrew; 08.08.2013
comment
В любом случае... мы отклоняемся от темы... :) - person Andrew; 08.08.2013

Я бы написал так, потому что else избыточен:

   if (a < b) {
       return 0;  // bail, since condition is met
   }
   // lots of calculations in this block
   return 1;

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

Однако, например, в рекурсивной функции очень удобно помещать ваши «базовые случаи» в качестве операторов возврата в начале функции.

Например, рассмотрим факториал:

int fact(int x) {
  // base cases
  if (x == 0 || x == 1)
    return 1;

  // recursive call
  return x * fact(x-1);
}

Вы также можете написать это так:

int fact(int x) {
  int ret = 0;
  if (x == 0 || x == 1)
    ret = 1;
  else
    ret = x * fact(x-1);
  return ret;
}

Мне просто больше нравится первый способ, но это не значит, что любой способ лучше другого.

Это действительно сводится к тем стандартам, которым вы должны следовать, и личным предпочтениям.

person dcp    schedule 18.06.2013

Некоторые считают это плохой практикой, я лично согласен с этим, так как это может быть более чистый код. Вы также можете сделать это следующим образом:

foo() {
   int results = 0;  // good practice to initialize
   if (a < b) {
       results = 0;  // redundant, likely optimized out
   } else {
       // lots of calculations in this block
       results = 1;
   }
   return results;
}
person mark    schedule 18.06.2013

Множественные операторы возврата вполне допустимы в C/C++. Но убедитесь, что по крайней мере один из операторов return всегда выполняется. Следующая функция неверна,

int foo(int x)
{
  if(x>0)
  {
    return 1;
  }
  else if(x==0)
  {
    return 0;
  }
  else
  {
    // No return in this block
  }
}

таких ситуаций следует избегать в C/C++.

person Deepu    schedule 18.06.2013

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

Просто убедитесь, что если ваша функция не имеет возвращаемого типа void, то у вас есть оператор return в конце, и что все операторы возврата возвращают этот тип. Например, если ваша функция объявлена ​​так:

int foo ();

Тогда все ваши операторы return должны возвращать целые числа, и вы должны возвращать целое число в конце, несмотря ни на что. Но если ваша функция имеет возвращаемый тип void, например:

void foo ();

Затем, если вы дойдете до конца функции и у вас не будет ключевого слова return, функция вернется автоматически.

person creXALBO    schedule 18.06.2013
comment
Вау, очень интересное понимание - person user1135541; 19.06.2013