6

I am working on embedded C. Could somebody help me which piece of code?

Is efficient in terms of robustness, memory as well as Misra friendly?

Code1:

if (func() == 1 || func() == 2) {
    /* Body of the function */ 
}

Code2:

locvar = func();

if (locvar == 1 || locvar == 2) {
    /* Body of the function */    
}
Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • 11
    The two code snippets do different things! Do the function `func` have any side-effects? What happens if you call it twice compared to once? – Some programmer dude Jan 12 '22 at 08:05
  • 2
    If they are side-effect free, trust your compiler to optimize for you? – Chris Jan 12 '22 at 08:06
  • 7
    MISRA-C:2012 does not allow the right operand of `||` to contain side effects. Also it requires that sub-expressions are surrounded by parenthesis. Well I guess this could be an answer, voting to re-open. – Lundin Jan 12 '22 at 08:24
  • 3
    @Chris how far can you rely on your compiler to detect that if the called function is not defined in same compilation unit but in some other C file or some dynamic library? I would not expect much in these cases. – Gerhardh Jan 12 '22 at 08:29

3 Answers3

7

As noted, the two examples may do different things and give different results.

MISRA-C compliance and robustness go hand in hand. As for memory use, it's not an issue in this code.

The first example is likely not robust nor MISRA compliant: specifically, MISRA-C:2012 rule 13.5 bans the right operand of && and || from containing persistent side effects.

Furthermore, rules like 12.1 requires sub expressions of large expressions to be surrounded by parenthesis, to make operator precedence explicit.

A MISRA-C compliant version would be something like:

locvar = func();

if ((locvar == 1) || (locvar == 2)) {
  ...
}
Lundin
  • 195,001
  • 40
  • 254
  • 396
4

Further to @Lundin's answer, the only MISRA C:2012 consideration is if there is a persistent side-effect within func() - if there are no persistent side-effects then MISRA C has little to say.

Likewise from a code efficiency perspective, an efficient compiler will (probably) optimise the code - it may even inline the function body anyway...

For me, the primary consideration would be code readability (and hence maintainability) - a single call makes it clear what you are doing... and if there are no persistent side-effects what is to be gained from making a second function call?

I vote for Code 2.

Andrew
  • 2,046
  • 1
  • 24
  • 37
0

In theory, computing the value used in the branch condition can improve branch prediction for the processor, but an optimizing compiler should do this for you. In think this answer might be interesting:

conditional data transfers VS n conditional control transfers(using conditional mov) in Assembly

  • 1
    This is not really a full answer. In the future, it would be better to leave this kind of response as a comment. – charlesw Jan 13 '22 at 03:45
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 13 '22 at 03:46