Jump to 
content
HP.com Home Products and Services Support and Drivers Solutions How to Buy
»  Contact HP

 

HP C

HP C
Language Reference Manual


Previous Contents Index

7.6.3 The for Statement

The for statement evaluates three expressions and executes the loop body until the second controlling expression evaluates to false (0). The for statement is useful for executing a loop body a specified number of times. The for statement has the following syntax:

for ( expression-1opt ; 

  • expression-2opt ; expression-3opt)
  • statement

The for statement is equivalent to the following code:

expression-1; 


while ( expression-2 ) 

  • {
  • statement
  • expression-3 ;
  • }

The for statement executes the loop body zero or more times. Semicolons (;) are used to separate the control expressions. A for statement executes the following steps:

  1. expression-1 is evaluated once before the first iteration of the loop. This expression usually specifies the initial values for variables used in the loop.
  2. expression-2 is any scalar expression that determines whether to terminate the loop. expression-2 is evaluated before each loop iteration. If the expression is true (nonzero), the loop body is executed. If the expression is false (0), execution of the for statement terminates.
  3. expression-3 is evaluated after each iteration.
  4. The for statement executes until expression-2 is false (0), or until a jump statement, such as break or goto, terminates execution of the loop.

Any of the three expressions in a for loop can be omitted:

  • If expression-2 is omitted, the test condition is always true; that is, the while loop equivalent becomes while(1). This is an infinite loop. For example:


    for (i = 0;  ;i++) 
        statement; 
    

    Infinite loops can be terminated with a break, return, or goto statement within the loop body.

  • If either expression-1 or expression-3 is omitted from the for statement, the omitted expression is evaluated as a void expression and is effectively dropped from the expansion. For example:


    n = 1; 
    for ( ; n < 10; n++) 
       func(n); 
    

    In this example, n is initialized before the for statement is executed.

In relaxed ANSI C mode, the first clause of the for statement can be a declaration whose scope includes the remaining clauses of the for header and the entire loop body. This is normally used to declare and initialize a local loop control variable. For example:


for (int i=0; i<10; i++) 
    printf("%d\n", i); 

7.7 Jump Statements

Jump statements cause an unconditional jump to another statement elsewhere in the code. They are used primarily to interrupt switch statements and loops.

The jump statements are the goto statement, the continue statement, the break statement, and the return statement, which are discussed in the following sections.

7.7.1 The goto Statement

The goto statement unconditionally transfers program control to a labeled statement, where the label identifier is in the scope of the function containing the goto statement. The labeled statement is the next statement executed. The goto statement has the following syntax:

goto identifier; 

Care must be taken when branching into a block by using the goto statement, because storage is allocated for automatic variables declared within a block when the block is activated. When a goto statement branches into a block, automatic variables declared in the block are not initialized.

7.7.2 The continue Statement

The continue statement passes control to the end of the immediately enclosing while, do, or for statement. The continue statement has the following syntax:

continue; 

The continue statement is equivalent to a goto statement within an iteration statement that passes control to the end of the loop body. For example, the following two loops are equivalent:


while(1)                           while(1) 
{                                  { 
   .                                  . 
   .                                  . 
   .                                  . 
  goto label_1;                     continue; 
   .                                  . 
   .                                  . 
   .                                  . 
  label_1:                        
   ;                                  ; 
 }                                  } 

The continue statement can be used only in loops. A continue inside a switch statement that is inside a loop causes continued execution of the enclosing loop after exiting from the body of the switch statement.

7.7.3 The break Statement

The break statement terminates execution of the immediately enclosing while, do, for, or switch statement. Control passes to the statement following the loop body (or the compound statement of a switch statement). The break statement has the following syntax:

break; 

See Example 7-1 which uses a break statement within a switch statement.

7.7.4 The return Statement

The return statement terminates execution of a function and returns control to the calling function, with or without a return value. A function may contain any number of return statements. The return statement has the following syntax:

return expressionopt; 

If present, the expression is evaluated and its value is returned to the calling function. If necessary, its value is converted to the declared type of the containing function's return value.

A return statement with an expression cannot appear in a function whose return type is void. For more information about the void data type and function return types, see Sections 3.5 and 3.4.1.

If there is no expression and the function is not defined as void, the return value is undefined. For example, the following main function returns an unpredictable value to the operating system:


main ( ) 
  { 
   return; 
  } 

Reaching the closing brace that terminates a function is equivalent to executing a return statement without an expression.


Chapter 8
Preprocessor Directives and Predefined Macros

The C preprocessor provides the ability to perform macro substitution, conditional compilation, and inclusion of named files. Preprocessor directives, lines beginning with # and possibly preceded by white space, are used to communicate with the preprocessor.

The following sections describe the preprocessor directives and operators available with the HP C compiler:

Preprocessor directives are independent of the usual scope rules; they remain in effect from their occurrence until the end of the compilation unit or until their effect is canceled.

See Section 8.2 for more information about conditional compilation. See your platform-specific HP C documentation for implementation-defined information about preprocessor directives.

The ANSI standard allows only comments as text following a preprocessing directive. The HP C compiler issues a warning if this syntax rule is violated in all modes but the strict ANSI mode, in which it issues an error message.

8.1 Macro Definition (#define and #undef)

The #define directive specifies a macro identifier and a replacement list, and terminates with a new-line character. The replacement list, a sequence of preprocessing tokens, is substituted for every subsequent occurrence of that macro identifier in the program text, unless the identifier occurs inside a character constant, a comment, or a literal string. The #undef directive is used to cancel a definition for a macro.

A macro definition is independent of block structure, and is in effect from the #define directive that defines it until either a corresponding #undef directive or the end of the compilation unit is encountered.

The #define directive has the following syntax:

#define identifier replacement-list newline


#define identifier ( identifier-listopt ) 
replacement-list newline


#define identifier ( ... ) replacement-list newline


#define identifier ( identifier-list, ...  
replacement-list newline

If the replacement-list is empty, subsequent occurrences of the identifier are deleted from the source file.

The first form of the #define directive is called an object-like macro. The last three forms are called function-like macros.

The #undef directive has the following syntax:

#undef identifier newline

This directive cancels a previous definition of the identifier by #define. Redefining a macro previously defined is not legal, unless the new definition is precisely the same as the old.

The replacement list in the macro definition, as well as arguments in a function-like macro reference, can contain other macro references. HP C does not limit the depth to which such references can be nested.

For a given macro definition, any macro names contained in the replacement list are themselves replaced by their currently specified replacement lists. If a macro name being defined is contained in its own replacement list or in a nested replacement list, it is not replaced. These nonreplaced macro names are then no longer available for further replacement, even if they are later examined in contexts in which they would otherwise be replaced.

The following example shows nested #define directives:


/*  Show multiple substitutions and listing format. */ 
 
#define  AUTHOR  james + LAST 
 
main() 
{ 
   int writer,james,michener,joyce; 
 
   #define LAST michener 
   writer = AUTHOR; 
   #undef LAST 
   #define LAST joyce 
   writer = AUTHOR; 
} 

After this example is compiled with the appropriate options to show intermediate macro expansions, the following listing results:


    1            /* Show multiple substitutions and listing format. */ 
    2 
    3            #define AUTHOR james + LAST 
    4            
    5            main() 
    6            { 
    7              int writer, james, michener, joyce; 
    8            
    9              #define LAST michener 
   10              writer = AUTHOR; 
   10.1                     james + LAST 
   10.2                     michener 
   11              #undef LAST 
   12              #define LAST joyce 
   13              writer = AUTHOR; 
   13.1                     james + LAST 
   13.2                     joyce 
   14            } 

On the first pass, the compiler replaces the identifier AUTHOR with the replacement list james + LAST. On the second pass, the compiler replaces the identifier LAST with its currently defined replacement list value. At line 9, the replacement list value for LAST is the identifier michener, so michener is substituted at line 10. At line 12, the replacement list value for LAST is redefined to be the identifier joyce, so joyce is substituted at line 13.

The #define directive may be continued onto subsequent lines if necessary. To do this, end each line to be continued with a backslash (\) immediately followed by a new-line character. The backslash and new-line characters do not become part of the definition. The first character in the next line is logically adjacent to the character that immediately precedes the backslash. The backslash/newline as a continuation sequence is valid anywhere. However, comments within the definition line can be continued without the backslash/newline.

If you plan to port programs to and from other C implementations, take care in choosing which macro definitions to use within your programs, because some implementations define different macros than others.

8.1.1 Object-Like Form

A preprocessing directive of the following form defines an object-like macro that causes each subsequent occurrence of the macro name to be replaced by the replacement list:


#define identifier replacement-list newline

An object like macro may be redefined by another #define directive provided that the second definition is an object-like macro definition and the two replacement lists are identical. This means that two files, each with a definition of a certain macro, must be consistent in that definition.

The object-like form of macro definition defines a descriptive name for a frequently used token. A common use of the directive is to define the end-of-file (EOF) indicator as follows:


#define  EOF  (-1) 

8.1.2 Function-Like Form

The function-like form of macro definition includes a list of parameters. References to such macros look like function calls. When a function is called, control passes from the program to the function at run time; when a macro is referenced, source code is inserted into the program at compile time. The parameters are replaced by the corresponding arguments, and the text is inserted into the program stream.

If there is a ... in the identifier-list in the macro definition, then the trailing arguments, including any separating comma preprocessing tokens, are merged to form a single item: the variable arguments. The number of arguments so combined is such that, following the merger, the number of arguments is one more than the number of parameters in the macro definition (excluding the ...).

An identifier __VA_ARGS__ that occurs in the replacement-list of a function-like macro that uses ellipsis notation in the arguments is treated as if it were a parameter, and the variable arguments form the preprocessing tokens used to replace it.

If the replacement list is omitted from the macro definition, the entire macro reference disappears from the source text.

The library macro _toupper, available on some systems in the ctype.h header file, is a good example of macro replacement. This macro is defined as follows:


#define  _toupper(c)  ((c) >= 'a'  &&  (c) <= 'z'  ? (c) & 0X5F : (c)) 

When the macro _toupper is referenced, the compiler replaces the macro and its parameter with the replacement list from the directive, substituting the argument of the macro reference for each occurrence of the parameter (c in this case) in the replacement list.

The replacement list of C source code can be translated in the following manner: if parameter c is a lowercase letter (between 'a' and 'z'), the expression evaluates to an uppercase letter (c & 0X5F); otherwise, it evaluates to the character as specified. This replacement list uses the if-then-else conditional operator (?:). For more information about the conditional operator, see Section 6.6. For more information about the bitwise operators, see Section 6.5.6.

8.1.2.1 Rules for Specifying Macro Definitions

Preprocessor directives and macro references have syntax that is independent of the C language. Follow these rules when specifying macro definitions:

  • The macro name and the formal parameters are identifiers and are specified according to the rules for identifiers in the C language.
  • Spaces, tabs, and comments may be used freely within a #define directive anywhere that the delta symbol ( &Delta; ) appears in the following example:


    &Delta; #&Delta;define &Delta;  name(&Delta;parm1&Delta;,&Delta;parm2&Delta;)&Delta;\
     
    &Delta;token-string&Delta;
    

    Spaces, tabs, and comments are replaced by a single space.

  • White space cannot appear between the name and the left parenthesis that introduces the parameter list. White space may appear inside the replacement list. Also, at least one space, tab, or comment must separate name from define.
  • The identifier __VA_ARGS__ can occur only in the replacement-list of a function-like macro that uses the ellipsis notation in the arguments.

8.1.2.2 Rules for Specifying Macro References

Follow these rules when specifying macro references:

  • Comments and white-space characters (spaces, horizontal and vertical tabs, new-line characters, and form feeds) may be used freely within a macro reference anywhere that the delta symbol (<ucDelta symbol>) appears in the following example:


     &Delta;name&Delta;(&Delta;arg1&Delta;,&Delta;arg2&Delta;) 
    

  • Arguments consist of arbitrary text. Syntactically, they are not restricted to C expressions. They may contain embedded comments and white space. Comments are replaced with a single space. White space (except for leading and trailing white space) is preserved during the substitution.
  • The number of arguments in the reference must match the number of parameters in the macro definition. Null arguments result in undefined behavior.
  • Commas separate arguments except where the commas occur inside string or character constants, comments, or pairs of parentheses. Parentheses must be balanced within arguments.

8.1.2.3 Side Effects in Macro Arguments

It is not good programming practice to specify macro arguments that use the increment (++), decrement ( -- ), and assignment operators (such as +=) or other arguments that can cause side effects. For example, do not pass the following argument to the _toupper macro:


_toupper(p++) 

When the argument p++ is substituted in the macro definition, the effect within the program stream is as follows:


((p++) >= 'a' && (p++) <= 'z' ? (p++) & 0X5F : (p++)) 

Because p is being incremented, it does not have the same value for each occurrence in this macro replacement. Even if you are aware of possible side effects, the replacement lists within macro definitions can be changed, which changes the side effects without warning.

8.1.3 Conversions to String Literals (#)

The # preprocessor operator is used to convert the argument that follows it to a string literal. The preprocessor operator # can be used only in a function-like macro definition. For example:


#include <stdio.h> 
 
#define PR(id) printf("The value of " #id " is %d\n", id) 
 
main() 
{ 
 int i = 10; 
 
 PR(i); 
} 

The output produced is:


The value of i is 10 

The macro call expands in the following steps:


/*1*/  printf("The value of " #id " is %d\n", id) 
/*2*/  printf("The value of " "i" " is %d\n", 10) 
/*3*/  printf("The value of i is %d\n", 10) 

The unary # operator produces a string from its operand. This example also uses the fact that adjacent string literals are concatenated. If the operand to # contains double quotes or escape sequences, they are also expanded. For example:


#include <stdio.h> 
 
#define M(arg) printf(#arg " is %s\n", arg) 
 
main() 
{ 
 M("a\nb\tc"); 
} 

The macro call expands using the following steps:


/*1*/  printf(#arg " is %s\n", arg) 
/*2*/  printf("\"a\\nb\\tc\"" " is %s\n", "a\nb\tc"); 
/*3*/  printf("\"a\\nb\\tc\" is %s\n", "a\nb\tc"); 


Previous Next Contents Index

Privacy statement Using this site means you accept its terms
© 2007 Hewlett-Packard Development Company, L.P.