Hariom Singh
Hariom Singh

Reputation: 3632

MISRA C:2012 Rule 14.4

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

Upvotes: 5

Views: 10233

Answers (4)

kalehmann
kalehmann

Reputation: 5011

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.

Upvotes: 4

Lundin
Lundin

Reputation: 213428

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

Upvotes: 11

Andrew Henle
Andrew Henle

Reputation: 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 */

}

Upvotes: 1

Paul Ogilvie
Paul Ogilvie

Reputation: 25266

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)

Upvotes: 1

Related Questions