5

As per the MISRA rule The controlling expression of an if statement and the controlling expression of an iteration-statement shall have essentially Boolean type

#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 */

}

I am not able to understand how can it lead to a problem to use just the value .Why with if only adding a boolean expression is treated as good practise . Any insight will be helpful

Hariom Singh
  • 3,512
  • 6
  • 28
  • 52

4 Answers4

11

The rationale is provided with the rule: strong typing. The controlling expression should be essentially boolean type. The result of the equality, relational etc operators is to be regarded as essentially boolean, whereas showing in an int or pointer without an operator means that the expression is of the used type.

(As a side-note, this may be important for compatibility with C++ where a lot of operators actually return a bool, and may be overloaded with an operator function returning bool.)

The main reason is however not provided by MISRA, and that is self-documenting code. if(ptr != NULL) can only be a comparison of a pointer against NULL. No room for misunderstandings. if(ptr) could either be a comparison against NULL, or it could be an accidental slip of the finger and the programmer actually meant if(*ptr). Also, if the pointer has some cryptic name, it isn't obvious what if(xyz) does, but it is obvious what if(xyz != NULL) is.

This rule also prevents bugs such as if(func) where if(func()) was intended. Keep in mind that a lot of the MISRA rules are there for the benefit of a static analyser.


Regarding strong typing, consider this example:

#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");
    }
  }
}

Output:

x is true
but x is not true

y is true
I swear, y is really true
Lundin
  • 195,001
  • 40
  • 254
  • 396
4

Why with if only adding a boolean expression is treated as good practise?

"MISRA-C introduces a strong typing model to help users avoid unexpected issues which occur in the C typing model. The rule prevents the accidental use of integer expression when a boolean expression was intended. " as stated in the MISRA forum, as an "official" MISRA C WG answer

How can it lead to a problem to just use a integer in a if statement?

There is no way I can think of, but enforcing a consistent code style and philosophy in a project is important too.

Andrew
  • 2,046
  • 1
  • 24
  • 37
kalehmann
  • 4,821
  • 6
  • 26
  • 36
  • Are there compiler options to enable MISRA-C violation warnings? – Fiddling Bits Oct 12 '18 at 13:45
  • There are tools, that check if your code is MISRA-C compliant, however I think they are mostly proprietary – kalehmann Oct 12 '18 at 13:50
  • 2
    @FiddlingBits A few compilers like embedded systems IAR support MISRA plug-ins. The most common however, is to use an external MISRA checker/static analyser. Unfortunately they are all quite expensive and of diverse quality. – Lundin Oct 12 '18 at 13:57
1

I can't think of a particular reason.

I was thinking in the line of type conversions, where e.g. with a double d things could go wrong, but the double will be evaluated to be/not be 0.0 and so still is a valid expression for an if or iteration statement. Or a pointer to a character (string), but there too it will yield a valid expression.

So the only reason I can come up with is that it is now clear it is a boolean expression, i.e. better readability.

It would be good if MISRA would also check for the proper second operand, for example

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

which could also have been written as:

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

and for the double d:

if (d != 0.0)
Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41
1

One other possible reason could be to identify potential bugs like this:

#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 */

} 

or the more obvious

#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 */

}
Andrew Henle
  • 32,625
  • 3
  • 24
  • 56