C H A P T E R  11

image

Selection Statements

Covering packetC Basic Control Statements

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.

Compound Statement

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

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:

  • Conditional expressions that evaluate to a non-zero value are considered to be true; those that evaluate to zero are regarded as false.
  • The truth values produced by packetC conditional operators (logical, equality, and relational operators), however, are the int values 0 to indicate false and 1 to indicate true.
  • A conditional expression can consist of arbitrarily complex expressions that mix arithmetic and conditional operators that consist solely of operators that produce a truth value or consist solely of arithmetic operators.
    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
  • An arithmetic value that acts as a conditional expression must be an integer but is not restricted to the int type.
    byte b0 = 0, b1 = 2, b2 = 4;
    if ( b0 + b2 ) {…}                   // legal
  • Stand-alone enumeration type values cannot act as conditional expressions, because they cannot implicitly be treated as integers. However, such values can be type cast to perform this role or can be used with conditional operators.
    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 Statement

if  (  expression  )  statement
if  (  expression  )  statement  else  statement

The semantics of the packetC if statement are as follow:

  • The conditional expression's operands must have a scalar type.
  • If the conditional expression evaluates to a non-zero value, then the statement following the if keyword, which may be a compound statement, is executed and the statement following the else keyword (if present) is not.
  • If the conditional expression evaluates to the value 0, the statement associated with the if keyword is not executed but the statement associated with the else keyword is, if present.
  • An else clause is associated with the preceding if clause that is lexically closest to it and that has not been terminated by a semicolon.

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 Statement

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:

  • case alternatives are treated as structured statement components (i.e., similar to an if or else clause), rather than as labels.
  • Curly braces always enclose the entire collection of case and default alternatives, defining a local scope and allowing the presence of local declarations.
  • Statements and declarations may not appear between the opening curly brace and the initial alternative, whether the alternative is a case or the default alternative.
  • A default alternative must be present and must be the final alternative.
  • The only code that can appear within the switch statement body must consist of case or default alternatives.
// 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.

Null Statement

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
}

Expression 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;
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.138.120.187