Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Good C-coding style for multiple lines if conditions

I am programming a project in C and have a problem: I've got a lot of if conditions and it might get really hard for other people to read. I haven't yet found a similar question on the internet.

Do you have an idea or example how to make my code more readable?

Here is the C Code:

if( ((g_cycle_cnt == uartTxSecondaryMsg[3][msgPos[3]].sliceNo) ||   //correct slicenumber...
    (uartTxSecondaryMsg[3][msgPos[3]].sliceNo == -1) ||             // or as fast as possible...                                            

  ( (uartTxSecondaryMsg[3][msgPos[3]].sliceNo == -2) &&
   ((uartTxSecondaryMsg[3][msgPos[3]].timeFrameBegin>=g_uptime_cnt) && 
    (uartTxSecondaryMsg[3][msgPos[3]].timeFrameEnd<=g_uptime_cnt)))) &&

   ((dataProcessingFlag & SECONDARY_MSG_ANNOUNCED_CH4) == SECONDARY_MSG_ANNOUNCED_CH4) )
like image 783
En Kt Avatar asked Mar 29 '15 12:03

En Kt


People also ask

Can you put multiple conditions in an if statement in C?

Nested if statements mean an if statement inside another if statement. Yes, both C and C++ allow us to nested if statements within if statements, i.e, we can place an if statement inside another if statement.

How do you break up a long if statement?

Long if statements may be split onto several lines when the character/line limit would be exceeded. The conditions have to be positioned onto the following line, and indented 4 characters. The logical operators ( && , || , etc.)

How should I space my code?

Make 4 space indent, make sure no use tabs . Always use curly braces, even if the body is only one sentence. The if , else and if else keywords belong on separate lines by itself, no curly.

When we have multiple conditions and out of which only one is true which type of conditional statement we use?

The if-else-if statement is used to execute one code from multiple conditions. It is also called a multipath decision statement.


3 Answers

Create functions that have indicative names that check the requirements and represent their meaning e.g:

if( is_correct_slice_number(/*... params here ... */) || 
    is_asap(/*... params here ... */)  || 
    is_other_condition(/*... params here ... */))

Or as suggested macros that follow the same logic e.g:

if( IS_CORRECT_SLICE_NUMBER(/*... params here ... */) || 
    IS_ASAP(/*... params here ... */)  || 
    IS_OTHER_CONDITION(/*... params here ... */))

I think that this might make your intentions clearer.

like image 92
Scis Avatar answered Oct 19 '22 20:10

Scis


If you want to stick with your existing code (as opposed to factor things out into inline functions), and just modify the indentation, I'm a big fan of using indent consistently. This means you can fix any source file.

With its default options it gives you GNU indentation, i.e.:

if (((g_cycle_cnt == uartTxSecondaryMsg[3][msgPos[3]].sliceNo) ||       //correct slicenumber...
     (uartTxSecondaryMsg[3][msgPos[3]].sliceNo == -1) ||        // or as fast as possible...
     ((uartTxSecondaryMsg[3][msgPos[3]].sliceNo == -2) &&
      ((uartTxSecondaryMsg[3][msgPos[3]].timeFrameBegin >= g_uptime_cnt) &&
       (uartTxSecondaryMsg[3][msgPos[3]].timeFrameEnd <= g_uptime_cnt)))) &&
    ((dataProcessingFlag & SECONDARY_MSG_ANNOUNCED_CH4) ==
     SECONDARY_MSG_ANNOUNCED_CH4))
  {
    /* do something */
  }

I'd say that the problem here is in fact that you are poking about illegibly in arrays. At the very least, factor out:

uartTxSecondaryMsg[3][msgPos[3]]

into a separate variable, e.g.:

whatever *foo = &uartTxSecondaryMsg[3][msgPos[3]];
if (((g_cycle_cnt == foo->sliceNo) ||   //correct slicenumber...
     (foo->sliceNo == -1) ||    // or as fast as possible...
     ((foo->sliceNo == -2) &&
      ((foo->timeFrameBegin >= g_uptime_cnt) &&
       (foo->timeFrameEnd <= g_uptime_cnt)))) &&
    ((dataProcessingFlag & SECONDARY_MSG_ANNOUNCED_CH4) ==
     SECONDARY_MSG_ANNOUNCED_CH4))
  {
    /* do something */
  }

Obviously choose an appropriate type and variable name for foo.

You could then separate out the limbs of the if statement into separate functions each taking foo as a parameter.

like image 5
abligh Avatar answered Oct 19 '22 21:10

abligh


[this is very subjective]

  • remove excessive parentheses; they are defensive and obscure the meaning
  • properly align and order the conditions (possibly ignoring indentation rules)
  • (maybe) rewrite into another construct, such as a switch, or using early returns, or even goto

First step (cleanup and alignment):

if (    (  uartTxSecondaryMsg[3][msgPos[3]].sliceNo == g_cycle_cnt //correct slicenumber...
        || uartTxSecondaryMsg[3][msgPos[3]].sliceNo == -1          // or as fast as possible...                                
        ||(uartTxSecondaryMsg[3][msgPos[3]].sliceNo == -2
             && uartTxSecondaryMsg[3][msgPos[3]].timeFrameBegin >= g_uptime_cnt
             && uartTxSecondaryMsg[3][msgPos[3]].timeFrameEnd <= g_uptime_cnt
             && (dataProcessingFlag & SECONDARY_MSG_ANNOUNCED_CH4) == SECONDARY_MSG_ANNOUNCED_CH4 ) ) 
                {
                // do something useful here
                }

Second step, using switch (and goto !) [this could be a bit too much for some readers ...]

switch (uartTxSecondaryMsg[3][msgPos[3]].sliceNo) {
default:
    if (uartTxSecondaryMsg[3][msgPos[3]].sliceNo == g_cycle_cnt) goto process;
    break;
case -2:
    if (uartTxSecondaryMsg[3][msgPos[3]].timeFrameBegin < g_uptime_cnt) break;
    if (uartTxSecondaryMsg[3][msgPos[3]].timeFrameEnd > g_uptime_cnt) break;
    if ((dataProcessingFlag & SECONDARY_MSG_ANNOUNCED_CH4) != SECONDARY_MSG_ANNOUNCED_CH4) break;
case -1:
process:

          // do something useful here
 }

The advantage of the switch() construct is that it immediately clear that uartTxSecondaryMsg[3][msgPos[3]].sliceNo is the master condition. Another advantage is that cases and conditions can be added without having to interfere with the other cases or to struggle with the parentheses.

Now I hope I got the parentheses-removal right...

like image 2
wildplasser Avatar answered Oct 19 '22 21:10

wildplasser