While many programs can perform quite a lot in a straight-line list of algorithms operating on data, at some point, making some conditional branches in the logic becomes the only way to really progress from a simple formula into a program. Control flow statements fall into the conditional branching category as well as into looping. This chapter discusses the minor variations between packetC and C conditional branching while subsequent chapters cover looping.
Conditional branching represents the most basic control features within packetC, enabling the program to alternate its path through statements to achieve a complex goal. As values change in the application, multiple visits to the same conditional branch may result in alternate pathways being taken through the program. Furthermore, given that packetC is predominantly data-driven, conditional branching based upon packet data becomes a cornerstone to directing the pathway execution through the program.
All of the compound and conditional control statements that are available in C are present in packetC as well. This applies to the if-else statement as well as the switch-case statement in particular that are discussed in this chapter. While they are present, it doesn't mean that they are without some changes from C99 representation. Not to be difficult, but rather to really reflect a more modern representation of compound statements that support locality of declaration, packetC follows some C++ conventions as it addresses basic control statements.
The packetC compound statement allows variable and type declarations to be freely interspersed with executable statements. This follows C++ language convention, rather than that of standard C, which promotes the desirable software property, locality of declaration, in which programmers place the declarations for variables in close source code proximity to their use.
// Example
if ( condition_applies )
{ // start of compound stmt
counter++;
call_take_action( counter );
}
Conditional expressions can appear in stand-alone fashion or can govern the control flow of if, while, do-while, and for statements. The essential characteristics of conditional expressions are:
int a = 1, b = 2, c = 3;
if ( (a == b) && ( c - b ) ) {…} // mix operator types
if ( (b > c) || ( a < b ) ) {…} // all conditional operators
if ( a + b – c ) {…} // all arithmetic operators
byte b0 = 0, b1 = 2, b2 = 4;
if ( b0 + b2 ) {…} // legal
enum byte Hue = { RED, BLUE, GREEN } eVar = BLUE;
if ( eVar ) {…} // ERROR eVar is not an integer type
if ( (byte)eVar ) {…} // legal, eVar is cast to an integer type
if ( eVar != RED ) {…} // legal, != produces truth value result
if ( expression ) statement
if ( expression ) statement else statement
The semantics of the packetC if statement are as follow:
Traditional C if statements follow and should be familiar as the rules do not change.
// Examples
if ( k == 1 ) callAction1(b);
if ( k < j ) {
counter++;
callAction1(b);
}
if ( k != j ) {
callAction1(b);
}
else {
callAction2(b);
}
Additionally, while not shown, nesting of if statements and multiple else if statements is fully supported in packetC.
switch ( expression ) { case_alternative_listopt default : block_item_listopt }
case expression : block_item_listopt
Just as you would expect from C, a switch statement consists of a governing expression, an optional collection of case alternatives (each associated with a unique constant expression) and a default alternative. Execution begins by evaluating the governing expression. The statement or statement list associated with the first case alternative matching that expression is executed. If no break statement is encountered, control “falls through” to the next case alternative, as it does in C99. If no case alternative expression matches the governing expression, all statements associated with the default alternative are executed, if present, otherwise none of the case statements are executed.
The packetC switch statement differs from the C99 switch statement in the following ways:
// Example
switch ( myFlag ) {
case 0:
legalIntercept++;
analyzeFurther();
break;
case 1:
doOrdinaryPacketInspection();
// drops through to next "case"
default : nopCounter++;
}
The switch statement is suggested any time where multiple if conditions are necessary to support branching. In packetC, many optimizations may exist in the underlying system mapping switch statements to different data representations in order to drive rapid navigation through an application. In general, when more than a few comparisons are necessary with an if statement, a switch statement should be used wherever possible.
Although the null statement has no semantic program impact, it is structurally useful, e.g., for providing a no-operation default alternative in a switch statement.
// Example
switch (myEnum) {
case SEQUENCE_ISSUE:
checkSequence();
break;
case LEGAL_ISSUE:
doLegalIssueLog();
break;
…
default: ; // NULL statement
}
An expression statement is evaluated as a null expression. As in C99, typical use consists of calling a function to trigger its side effects or altering a value to control loop iteration.
// Examples
counter++;
--idx;
3.138.120.187