goto breaks the control flow and can lead to code that is difficult to comprehend. In addition, there are limitations for when goto can be used. For example, it is not permitted to jump past a statement that initializes a local object having a destructor.
Variables representing size or length are typical candidates for unsigned declarations. By following this recommendation some unpleasant errors can be avoided.
It is best to use inclusive lower and exclusive upper limits. Instead of saying that x is in the interval x>=23 and x<=42, use the limits x>=23 and x<43. The following important claims then apply:
- The size of the interval between the limits is the difference between the limits.
- The limits are equal if the interval is empty.
- The upper limit is never less than the lower limit.
By being consistent in this regard, many difficult errors will be avoided.
If the code which follows a case label is not terminated by break, the execution continues after the next case label. This means that poorly tested code can be erroneous and still seem to work.
continue can be used to exit from loops. However, code may be more comprehensible by using an else clause instead.
C++ has a very loose and, simultaneously, very free way of determining if an expression is true or false. If an expression is evaluated as 0, it is false; otherwise, it is considered to be true.
We do not recommend logical tests such as ''if(pointer)'' if ''pointer'' is a variable of pointer-type. The only reason is readablity; many programmers find it difficult to read such code.
Consider the scope within which an iteration variable is visible. A variable that is declared within a 'for' statement is currently only visible in the nearest enclosing block. The standardization committee for C++ is however discussing a language modification regarding this point. No decision has yet been made. Still, this problem is avoided if the control structure is encapsulated in a compound statement.
Example 56 Problem using unsigned loop variables
for( unsigned int i = 3; i >= 0; --i )
{
  // This loop will never terminate, since i cycles through:
  // 3, 2, 1, 0, 4294967295, 4294967294, etc ... on a SparcStation
  // Note that this example does not follow the rules: i >= 0
  // in the for statement. See next example !
}
Example 57 Visibility of variable declared in 'for' loop
for ( int index = 0; index < 10; index++ )
{
  cout << index
}
int index = 3 // ERROR, THIS IS AN ILLEGAL RE-DECLARATION OF index
                // BECAUSE index IS DECLARED IN BLOCK-SCOPE.
Example 58 Dangerous switch/case statement
switch ( tag )
{
  case A:
  {
      // Do something
      // Next statement is a call to foo() inside next case
  }
  case B:
  {
      foo()
      // Do something else
      break; // Now we leave the switch-statement
  }
  default:
  {
      // If no match in above cases, this is executed
      exit( 1 )
  }
}
Example 59 Good and bad ways of setting limits for loop variables
int a[10]
int ten = 10
int nine = 9
// Good way to do it:
for( int i = 0; i < ten; i++ )    // Loop runs 10-0=10 times
{
  a[i] = 0
}
// Bad way to do it:
for( int j = 0; j <= nine; j++ )  // Loop runs 10 times, but 9-0=9 !!!
{
  a[j] = 0
}
Example 60 Using break to exit a loop, no flags are needed.
do                                // This way:
{
  if ( Something )
  {
      // Do something
      break
  }
} while( someCondition )
int endFlag = 0                   // Is better than this:
do
{
  if ( /* Something */ )
  {
      // Do something
      endFlag = 1
  }
} while( someCondition && !endFlag );
Example 61 By using an extra 'else' clause, continue
is avoided and the code can be comprehended.
while( /* Something */ )                // This way is more clear
{
  if( /* Something */ )
  {
      // Do something
  }
  else
  {
      // Do something else
  }
}
while( /* Something */ )                // Than using continue
{
  if( /* Something */ )
  {
      // Do something
      continue; // No !
  }
  // Do something else
}