case
label must always be terminated by a break
statement.
switch
statement
must always contain a default
branch which handles
unexpected cases.
goto
.
for
, while
or do-while
) should
depend on the specific use of the loop.
unsigned
for
variables which cannot reasonably have negative values.
continue
.
break
to exit a loop
if this avoids the use of flags.
if(test)
or if(!test)
when
test
is a pointer.
Each loop construct has a specific usage. A for
loop
is used only when the loop variable is increased by a constant amount
for each iteration and when the termination of the loop is determined
by a constant expression. In other cases, while
or
do-while
should be used. When the terminating condition can
be evaluated at the beginning of the loop, while
should be
used; do-while
is used when the terminating condition is
best evaluated at the end of the loop.
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:
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.
case
labels are
followed by the same block of code, only one break
statement
is needed. Also, other statements than break
may be used
to exit a switch
statement, such as return
.
goto
may be permitted. Every such
usage must be carefully motivated.
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 ! }
for
' loopfor ( 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.
switch
/case
statementswitch ( 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 ); } }
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; }
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 );
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 }