MISRA C: 2012 Правило 14.4 - PullRequest
       18

MISRA C: 2012 Правило 14.4

0 голосов
/ 12 октября 2018

Согласно правилу MISRA Управляющее выражение оператора if и управляющее выражение оператора итерации должны иметь по существу логический тип

#include <stdbool.h>
#include <stdlib.h>

void foo(void){
    int i = 0;

    if(i){}              /* Non-compliant - int32_t is not boolean */

    if(i != 0){}         /* Compliant */

}

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

Ответы [ 4 ]

0 голосов
/ 12 октября 2018

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

(Как примечание, это может быть важно для совместимости с C ++, где многие операторы действительно возвращают bool и могут быть перегружены функцией operator, возвращающей bool.)

Однако основная причина не указана MISRA, а именно самодокументированным кодом.if(ptr != NULL) может быть только сравнением указателя с NULL.Нет места для недоразумений.if(ptr) может быть либо сравнением с NULL, либо случайным движением пальца, и программист действительно имел в виду if(*ptr).Кроме того, если указатель имеет какое-то загадочное имя, не очевидно, что делает if(xyz), но очевидно, что такое if(xyz != NULL).

Это правило также предотвращает ошибки, такие как if(func), где if(func()) был предназначен.Имейте в виду, что многие правила MISRA существуют для статического анализатора.


Что касается строгой типизации, рассмотрите следующий пример:

#include <stdio.h>
#include <stdbool.h>

int main (void)
{
  int x = false;
  x = ~x;

  if(x)
  {
    puts("x is true");
    if(x!=true)
    {
      puts("but x is not true\n");
    }
  }

  bool y = x;

  if(y)
  {
    puts("y is true");
    if(y==true)
    {
      puts("I swear, y is really true");
    }
  }
}

Вывод:

x is true
but x is not true

y is true
I swear, y is really true
0 голосов
/ 12 октября 2018

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

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

Как это может привести к проблеме, заключающейся в том, чтобы просто использовать целое число в операторе if?

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

0 голосов
/ 12 октября 2018

Еще одной возможной причиной может быть выявление потенциальных ошибок, таких как:

#include <stdbool.h>
#include <stdlib.h>

void foo(void){
    int i = 0;

    if(i){}              /* Non-compliant - int32_t is not boolean */

    if(i |= 0){}         /* Non-compliant - type is still int32_t */

} 

или более очевидных

#include <stdbool.h>
#include <stdlib.h>

void foo(void){
    int i = 0;

    if(i){}              /* Non-compliant - int32_t is not boolean */

    if(i = 0){}         /* Non-compliant */

}
0 голосов
/ 12 октября 2018

Я не могу придумать конкретную причину.

Я думал в строке преобразования типов, где, например, с двойным d все может пойти не так, но двойное будет оценено как/ not быть 0.0 и поэтому все еще является допустимым выражением для оператора if или итерации.Или указатель на символ (строку), но там он также даст правильное выражение.

Поэтому единственная причина, по которой я могу придумать, состоит в том, что теперь ясно, что это логическое выражение, то есть лучшая читаемость.

Было бы хорошо, если бы MISRA также проверил правильный второй операнд, например,

char *s;
if (s != NULL && *s != '\0')

, который также мог бы быть записан как:

if (s != 0 && *s != 0)

а для двойных d:

if (d != 0.0)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...