Programming languages — C (INTERNATIONAL STANDARD ISO/IEC 9899:TC3) - page 7

 

  Главная      Manuals     Programming languages — C (INTERNATIONAL STANDARD ISO/IEC 9899:TC3) - 2007 year

 

Search            copyright infringement  

 

 

 

 

 

 

 

 

 

 

 

Content      ..     5      6      7      8     ..

 

 

 

Programming languages — C (INTERNATIONAL STANDARD ISO/IEC 9899:TC3) - page 7

 

 

6.7.8 Initialization

Syntax

1

initializer:

assignment-expression

{

initializer-list

}

{

initializer-list

, }

initializer-list:

designation

opt

initializer

initializer-list

,

designation

opt

initializer

designation:

designator-list

=

designator-list:

designator
designator-list designator

designator:

[

constant-expression

]

.

identifier

Constraints

2

No initializer shall attempt to provide a value for an object not contained within the entity
being initialized.

3

The type of the entity to be initialized shall be an array of unknown size or an object type
that is not a variable length array type.

4

All the expressions in an initializer for an object that has static storage duration shall be
constant expressions or string literals.

5

If the declaration of an identifier has block scope, and the identifier has external or
internal linkage, the declaration shall have no initializer for the identifier.

6

If a designator has the form

[

constant-expression

]

then the current object (defined below) shall have array type and the expression shall be
an integer constant expression. If the array is of unknown size, any nonnegative value is
valid.

7

If a designator has the form

.

identifier

then the current object (defined below) shall have structure or union type and the
identifier shall be the name of a member of that type.
§6.7.8 Language

125

Semantics

8

An initializer specifies the initial value stored in an object.

9

Except where explicitly stated otherwise, for the purposes of this subclause unnamed
members of objects of structure and union type do not participate in initialization.
Unnamed members of structure objects have indeterminate value even after initialization.

10

If an object that has automatic storage duration is not initialized explicitly, its value is
indeterminate. If an object that has static storage duration is not initialized explicitly,
then:

— if it has pointer type, it is initialized to a null pointer;

— if it has arithmetic type, it is initialized to (positive or unsigned) zero;

— if it is an aggregate, every member is initialized (recursively) according to these rules;

— if it is a union, the first named member is initialized (recursively) according to these

rules.

11

The initializer for a scalar shall be a single expression, optionally enclosed in braces. The
initial value of the object is that of the expression (after conversion); the same type
constraints and conversions as for simple assignment apply, taking the type of the scalar
to be the unqualified version of its declared type.

12

The rest of this subclause deals with initializers for objects that have aggregate or union
type.

13

The initializer for a structure or union object that has automatic storage duration shall be
either an initializer list as described below, or a single expression that has compatible
structure or union type. In the latter case, the initial value of the object, including
unnamed members, is that of the expression.

14

An array of character type may be initialized by a character string literal, optionally
enclosed in braces. Successive characters of the character string literal (including the
terminating null character if there is room or if the array is of unknown size) initialize the
elements of the array.

15

An array with element type compatible with

wchar_t

may be initialized by a wide

string literal, optionally enclosed in braces. Successive wide characters of the wide string
literal (including the terminating null wide character if there is room or if the array is of
unknown size) initialize the elements of the array.

16

Otherwise, the initializer for an object that has aggregate or union type shall be a brace-
enclosed list of initializers for the elements or named members.

17

Each brace-enclosed initializer list has an associated current object. When no
designations are present, subobjects of the current object are initialized in order according
to the type of the current object: array elements in increasing subscript order, structure

126 Language

§6.7.8

members in declaration order, and the first named member of a union.

129)

In contrast, a

designation causes the following initializer to begin initialization of the subobject
described by the designator. Initialization then continues forward in order, beginning
with the next subobject after that described by the designator.

130)

18

Each designator list begins its description with the current object associated with the
closest surrounding brace pair. Each item in the designator list (in order) specifies a
particular member of its current object and changes the current object for the next
designator (if any) to be that member.

131)

The current object that results at the end of the

designator list is the subobject to be initialized by the following initializer.

19

The initialization shall occur in initializer list order, each initializer provided for a
particular subobject overriding any previously listed initializer for the same subobject;

132)

all subobjects that are not initialized explicitly shall be initialized implicitly the same as
objects that have static storage duration.

20

If the aggregate or union contains elements or members that are aggregates or unions,
these rules apply recursively to the subaggregates or contained unions. If the initializer of
a subaggregate or contained union begins with a left brace, the initializers enclosed by
that brace and its matching right brace initialize the elements or members of the
subaggregate or the contained union. Otherwise, only enough initializers from the list are
taken to account for the elements or members of the subaggregate or the first member of
the contained union; any remaining initializers are left to initialize the next element or
member of the aggregate of which the current subaggregate or contained union is a part.

21

If there are fewer initializers in a brace-enclosed list than there are elements or members
of an aggregate, or fewer characters in a string literal used to initialize an array of known
size than there are elements in the array, the remainder of the aggregate shall be
initialized implicitly the same as objects that have static storage duration.

22

If an array of unknown size is initialized, its size is determined by the largest indexed
element with an explicit initializer. At the end of its initializer list, the array no longer
has incomplete type.

129) If the initializer list for a subaggregate or contained union does not begin with a left brace, its

subobjects are initialized as usual, but the subaggregate or contained union does not become the
current object: current objects are associated only with brace-enclosed initializer lists.

130) After a union member is initialized, the next object is not the next member of the union; instead, it is

the next subobject of an object containing the union.

131) Thus, a designator can only specify a strict subobject of the aggregate or union that is associated with

the surrounding brace pair. Note, too, that each separate designator list is independent.

132) Any initializer for the subobject which is overridden and so not used to initialize that subobject might

not be evaluated at all.

§6.7.8 Language

127

23

The order in which any side effects occur among the initialization list expressions is
unspecified.

133)

24

EXAMPLE 1

Provided that

<complex.h>

has been

#include

d, the declarations

int i = 3.5;

double complex c = 5 + 3 * I;

define and initialize

i

with the value 3 and

c

with the value

5. 0

+

i3. 0

.

25

EXAMPLE 2

The declaration

int x[] = { 1, 3, 5 };

defines and initializes

x

as a one-dimensional array object that has three elements, as no size was specified

and there are three initializers.

26

EXAMPLE 3

The declaration

int y[4][3] = {

{ 1, 3, 5 },

{ 2, 4, 6 },

{ 3, 5, 7 },

};

is a definition with a fully bracketed initialization: 1, 3, and 5 initialize the first row of

y

(the array object

y[0]

), namely

y[0][0]

,

y[0][1]

, and

y[0][2]

. Likewise the next two lines initialize

y[1]

and

y[2]

. The initializer ends early, so

y[3]

is initialized with zeros. Precisely the same effect could have

been achieved by

int y[4][3] = {

1, 3, 5, 2, 4, 6, 3, 5, 7

};

The initializer for

y[0]

does not begin with a left brace, so three items from the list are used. Likewise the

next three are taken successively for

y[1]

and

y[2]

.

27

EXAMPLE 4

The declaration

int z[4][3] = {

{ 1 }, { 2 }, { 3 }, { 4 }

};

initializes the first column of

z

as specified and initializes the rest with zeros.

28

EXAMPLE 5

The declaration

struct { int a[3], b; } w[] = { { 1 }, 2 };

is a definition with an inconsistently bracketed initialization. It defines an array with two element
structures:

w[0].a[0]

is 1 and

w[1].a[0]

is 2; all the other elements are zero.

133) In particular, the evaluation order need not be the same as the order of subobject initialization.

128 Language

§6.7.8

29

EXAMPLE 6

The declaration

short q[4][3][2] = {

{ 1 },

{ 2, 3 },

{ 4, 5, 6 }

};

contains an incompletely but consistently bracketed initialization. It defines a three-dimensional array
object:

q[0][0][0]

is 1,

q[1][0][0]

is 2,

q[1][0][1]

is 3, and 4, 5, and 6 initialize

q[2][0][0]

,

q[2][0][1]

, and

q[2][1][0]

, respectively; all the rest are zero. The initializer for

q[0][0]

does not begin with a left brace, so up to six items from the current list may be used. There is

only one, so the values for the remaining five elements are initialized with zero. Likewise, the initializers
for

q[1][0]

and

q[2][0]

do not begin with a left brace, so each uses up to six items, initializing their

respective two-dimensional subaggregates. If there had been more than six items in any of the lists, a
diagnostic message would have been issued. The same initialization result could have been achieved by:

short q[4][3][2] = {

1, 0, 0, 0, 0, 0,

2, 3, 0, 0, 0, 0,

4, 5, 6

};

or by:

short q[4][3][2] = {

{

{ 1 },

},

{

{ 2, 3 },

},

{

{ 4, 5 },

{ 6 },

}

};

in a fully bracketed form.

30

Note that the fully bracketed and minimally bracketed forms of initialization are, in general, less likely to
cause confusion.

31

EXAMPLE 7

One form of initialization that completes array types involves typedef names. Given the

declaration

typedef int A[];

//

OK - declared with block scope

the declaration

A a = { 1, 2 }, b = { 3, 4, 5 };

is identical to

int a[] = { 1, 2 }, b[] = { 3, 4, 5 };

due to the rules for incomplete types.

§6.7.8 Language

129

32

EXAMPLE 8

The declaration

char s[] = "abc", t[3] = "abc";

defines ‘‘plain’’

char

array objects

s

and

t

whose elements are initialized with character string literals.

This declaration is identical to

char s[] = { 'a', 'b', 'c', '\0' },

t[] = { 'a', 'b', 'c' };

The contents of the arrays are modifiable. On the other hand, the declaration

char *p = "abc";

defines

p

with type ‘‘pointer to

char

’’ and initializes it to point to an object with type ‘‘array of

char

’’

with length 4 whose elements are initialized with a character string literal. If an attempt is made to use

p

to

modify the contents of the array, the behavior is undefined.

33

EXAMPLE 9

Arrays can be initialized to correspond to the elements of an enumeration by using

designators:

enum { member_one, member_two };

const char *nm[] = {

[member_two] = "member two",

[member_one] = "member one",

};

34

EXAMPLE 10

Structure members can be initialized to nonzero values without depending on their order:

div_t answer = { .quot = 2, .rem = -1 };

35

EXAMPLE 11

Designators can be used to provide explicit initialization when unadorned initializer lists

might be misunderstood:

struct { int a[3], b; } w[] =

{ [0].a = {1}, [1].a[0] = 2 };

36

EXAMPLE 12

Space can be ‘‘allocated’’ from both ends of an array by using a single designator:

int a[MAX] = {

1, 3, 5, 7, 9, [MAX-5] = 8, 6, 4, 2, 0

};

37

In the above, if

MAX

is greater than ten, there will be some zero-valued elements in the middle; if it is less

than ten, some of the values provided by the first five initializers will be overridden by the second five.

38

EXAMPLE 13

Any member of a union can be initialized:

union { /*

...

*/ } u = { .any_member = 42 };

Forward references: common definitions

<stddef.h>

(7.17).

130 Language

§6.7.8

6.8 Statements and blocks

Syntax

1

statement:

labeled-statement
compound-statement
expression-statement
selection-statement
iteration-statement
jump-statement

Semantics

2

statement specifies an action to be performed. Except as indicated, statements are
executed in sequence.

3

block allows a set of declarations and statements to be grouped into one syntactic unit.
The initializers of objects that have automatic storage duration, and the variable length
array declarators of ordinary identifiers with block scope, are evaluated and the values are
stored in the objects (including storing an indeterminate value in objects without an
initializer) each time the declaration is reached in the order of execution, as if it were a
statement, and within each declaration in the order that declarators appear.

4

full expression is an expression that is not part of another expression or of a declarator.
Each of the following is a full expression: an initializer; the expression in an expression
statement; the controlling expression of a selection statement (

if

or

switch

); the

controlling expression of a

while

or

do

statement; each of the (optional) expressions of

a

for

statement; the (optional) expression in a

return

statement. The end of a full

expression is a sequence point.

Forward references: expression and null statements (6.8.3), selection statements
(6.8.4), iteration statements (6.8.5), the

return

statement (6.8.6.4).

6.8.1 Labeled statements

Syntax

1

labeled-statement:

identifier

:

statement

case

constant-expression

:

statement

default :

statement

Constraints

2

A

case

or

default

label shall appear only in a

switch

statement. Further

constraints on such labels are discussed under the

switch

statement.

§6.8.1 Language

131

3

Label names shall be unique within a function.

Semantics

4

Any statement may be preceded by a prefix that declares an identifier as a label name.
Labels in themselves do not alter the flow of control, which continues unimpeded across
them.

Forward references: the

goto

statement (6.8.6.1), the

switch

statement (6.8.4.2).

6.8.2 Compound statement

Syntax

1

compound-statement:

{

block-item-list

opt

}

block-item-list:

block-item
block-item-list block-item

block-item:

declaration
statement

Semantics

2

compound statement is a block.

6.8.3 Expression and null statements

Syntax

1

expression-statement:

expression

opt

;

Semantics

2

The expression in an expression statement is evaluated as a void expression for its side
effects.

134)

3

null statement (consisting of just a semicolon) performs no operations.

4

EXAMPLE 1

If a function call is evaluated as an expression statement for its side effects only, the

discarding of its value may be made explicit by converting the expression to a void expression by means of
a cast:

int p(int);

/*

...

*/

(void)p(0);

134) Such as assignments, and function calls which have side effects.

132 Language

§6.8.3

5

EXAMPLE 2

In the program fragment

char *s;

/*

...

*/

while (*s++ != '\0')

;

a null statement is used to supply an empty loop body to the iteration statement.

6

EXAMPLE 3

A null statement may also be used to carry a label just before the closing

}

of a compound

statement.

while (loop1) {

/*

...

*/

while (loop2) {

/*

...

*/

if (want_out)

goto end_loop1;

/*

...

*/

}

/*

...

*/

end_loop1: ;

}

Forward references: iteration statements (6.8.5).

6.8.4 Selection statements

Syntax

1

selection-statement:

if (

expression

)

statement

if (

expression

)

statement

else

statement

switch (

expression

)

statement

Semantics

2

A selection statement selects among a set of statements depending on the value of a
controlling expression.

3

A selection statement is a block whose scope is a strict subset of the scope of its
enclosing block. Each associated substatement is also a block whose scope is a strict
subset of the scope of the selection statement.

6.8.4.1 The

if

statement

Constraints

1

The controlling expression of an

if

statement shall have scalar type.

Semantics

2

In both forms, the first substatement is executed if the expression compares unequal to 0.
In the

else

form, the second substatement is executed if the expression compares equal

§6.8.4.1 Language

133

to 0. If the first substatement is reached via a label, the second substatement is not
executed.

3

An

else

is associated with the lexically nearest preceding

if

that is allowed by the

syntax.

6.8.4.2 The

switch

statement

Constraints

1

The controlling expression of a

switch

statement shall have integer type.

2

If a

switch

statement has an associated

case

or

default

label within the scope of an

identifier with a variably modified type, the entire

switch

statement shall be within the

scope of that identifier.

135)

3

The expression of each

case

label shall be an integer constant expression and no two of

the

case

constant expressions in the same

switch

statement shall have the same value

after conversion. There may be at most one

default

label in a

switch

statement.

(Any enclosed

switch

statement may have a

default

label or

case

constant

expressions with values that duplicate

case

constant expressions in the enclosing

switch

statement.)

Semantics

4

A

switch

statement causes control to jump to, into, or past the statement that is the

switch body, depending on the value of a controlling expression, and on the presence of a

default

label and the values of any

case

labels on or in the switch body. A

case

or

default

label is accessible only within the closest enclosing

switch

statement.

5

The integer promotions are performed on the controlling expression. The constant
expression in each

case

label is converted to the promoted type of the controlling

expression. If a converted value matches that of the promoted controlling expression,
control jumps to the statement following the matched

case

label. Otherwise, if there is

a

default

label, control jumps to the labeled statement. If no converted

case

constant

expression matches and there is no

default

label, no part of the switch body is

executed.

Implementation limits

6

As discussed in 5.2.4.1, the implementation may limit the number of

case

values in a

switch

statement.

135) That is, the declaration either precedes the

switch

statement, or it follows the last

case

or

default

label associated with the

switch

that is in the block containing the declaration.

134 Language

§6.8.4.2

7

EXAMPLE In the artificial program fragment

switch (expr)

{

int i = 4;

f(i);

case 0:

i = 17;

/*

falls through into

default

code

*/

default:

printf("%d\n", i);

}

the object whose identifier is

i

exists with automatic storage duration (within the block) but is never

initialized, and thus if the controlling expression has a nonzero value, the call to the

printf

function will

access an indeterminate value. Similarly, the call to the function

f

cannot be reached.

6.8.5 Iteration statements

Syntax

1

iteration-statement:

while (

expression

)

statement

do

statement

while (

expression

) ;

for (

expression

opt

;

expression

opt

;

expression

opt

)

statement

for (

declaration expression

opt

;

expression

opt

)

statement

Constraints

2

The controlling expression of an iteration statement shall have scalar type.

3

The declaration part of a

for

statement shall only declare identifiers for objects having

storage class

auto

or

register

.

Semantics

4

An iteration statement causes a statement called the loop body to be executed repeatedly
until the controlling expression compares equal to 0. The repetition occurs regardless of
whether the loop body is entered from the iteration statement or by a jump.

136)

5

An iteration statement is a block whose scope is a strict subset of the scope of its
enclosing block. The loop body is also a block whose scope is a strict subset of the scope
of the iteration statement.

136) Code jumped over is not executed. In particular, the controlling expression of a

for

or

while

statement is not evaluated before entering the loop body, nor is clause-1 of a

for

statement.

§6.8.5 Language

135

6.8.5.1 The

while

statement

1

The evaluation of the controlling expression takes place before each execution of the loop
body.

6.8.5.2 The

do

statement

1

The evaluation of the controlling expression takes place after each execution of the loop
body.

6.8.5.3 The

for

statement

1

The statement

for (

clause-1

;

expression-2

;

expression-3

)

statement

behaves as follows: The expression expression-2 is the controlling expression that is
evaluated before each execution of the loop body. The expression expression-3 is
evaluated as a void expression after each execution of the loop body. If clause-1 is a
declaration, the scope of any identifiers it declares is the remainder of the declaration and
the entire loop, including the other two expressions; it is reached in the order of execution
before the first evaluation of the controlling expression. If clause-1 is an expression, it is
evaluated as a void expression before the first evaluation of the controlling expression.

137)

2

Both clause-1 and expression-3 can be omitted. An omitted expression-2 is replaced by a
nonzero constant.

6.8.6 Jump statements

Syntax

1

jump-statement:

goto

identifier

;

continue ;

break ;

return

expression

opt

;

Semantics

2

A jump statement causes an unconditional jump to another place.

137) Thus, clause-1 specifies initialization for the loop, possibly declaring one or more variables for use in

the loop; the controlling expression, expression-2, specifies an evaluation made before each iteration,
such that execution of the loop continues until the expression compares equal to 0; and expression-3
specifies an operation (such as incrementing) that is performed after each iteration.

136 Language

§6.8.6

6.8.6.1 The

goto

statement

Constraints

1

The identifier in a

goto

statement shall name a label located somewhere in the enclosing

function. A

goto

statement shall not jump from outside the scope of an identifier having

a variably modified type to inside the scope of that identifier.

Semantics

2

A

goto

statement causes an unconditional jump to the statement prefixed by the named

label in the enclosing function.

3

EXAMPLE 1

It is sometimes convenient to jump into the middle of a complicated set of statements. The

following outline presents one possible approach to a problem based on these three assumptions:

1. The general initialization code accesses objects only visible to the current function.

2. The general initialization code is too large to warrant duplication.

3. The code to determine the next operation is at the head of the loop. (To allow it to be reached by

continue

statements, for example.)

/*

...

*/

goto first_time;

for (;;) {

//

determine next operation

/*

...

*/

if (

need to reinitialize

) {

//

reinitialize-only code

/*

...

*/

first_time:

//

general initialization code

/*

...

*/

continue;

}

//

handle other operations

/*

...

*/

}

§6.8.6.1 Language

137

4

EXAMPLE 2

A

goto

statement is not allowed to jump past any declarations of objects with variably

modified types. A jump within the scope, however, is permitted.

goto lab3;

//

invalid: going INTO scope of VLA

.

{

double a[n];

a[j] = 4.4;

lab3:

a[j] = 3.3;

goto lab4;

//

valid: going WITHIN scope of VLA

.

a[j] = 5.5;

lab4:

a[j] = 6.6;

}

goto lab4;

//

invalid: going INTO scope of VLA

.

6.8.6.2 The

continue

statement

Constraints

1

A

continue

statement shall appear only in or as a loop body.

Semantics

2

A

continue

statement causes a jump to the loop-continuation portion of the smallest

enclosing iteration statement; that is, to the end of the loop body. More precisely, in each
of the statements

while (/*

...

*/) {

/*

...

*/

continue;

/*

...

*/

contin: ;

}

do {

/*

...

*/

continue;

/*

...

*/

contin: ;

} while (/*

...

*/);

for (/*

...

*/) {

/*

...

*/

continue;

/*

...

*/

contin: ;

}

unless the

continue

statement shown is in an enclosed iteration statement (in which

case it is interpreted within that statement), it is equivalent to

goto contin;

.

138)

6.8.6.3 The

break

statement

Constraints

1

A

break

statement shall appear only in or as a switch body or loop body.

Semantics

2

A

break

statement terminates execution of the smallest enclosing

switch

or iteration

statement.

138) Following the

contin:

label is a null statement.

138 Language

§6.8.6.3

6.8.6.4 The

return

statement

Constraints

1

A

return

statement with an expression shall not appear in a function whose return type

is

void

. A

return

statement without an expression shall only appear in a function

whose return type is

void

.

Semantics

2

A

return

statement terminates execution of the current function and returns control to

its caller. A function may have any number of

return

statements.

3

If a

return

statement with an expression is executed, the value of the expression is

returned to the caller as the value of the function call expression. If the expression has a
type different from the return type of the function in which it appears, the value is
converted as if by assignment to an object having the return type of the function.

139)

4

EXAMPLE In:

struct s { double i; } f(void);

union {

struct {

int f1;

struct s f2;

} u1;

struct {

struct s f3;

int f4;

} u2;

} g;

struct s f(void)

{

return g.u1.f2;

}

/*

...

*/

g.u2.f3 = f();

there is no undefined behavior, although there would be if the assignment were done directly (without using
a function call to fetch the value).

139) The

return

statement is not an assignment. The overlap restriction of subclause 6.5.16.1 does not

apply to the case of function return. The representation of floating-point values may have wider range
or precision and is determined by

FLT_EVAL_METHOD

. A cast may be used to remove this extra

range and precision.

§6.8.6.4 Language

139

6.9 External definitions

Syntax

1

translation-unit:

external-declaration
translation-unit external-declaration

external-declaration:

function-definition
declaration

Constraints

2

The storage-class specifiers

auto

and

register

shall not appear in the declaration

specifiers in an external declaration.

3

There shall be no more than one external definition for each identifier declared with
internal linkage in a translation unit. Moreover, if an identifier declared with internal
linkage is used in an expression (other than as a part of the operand of a

sizeof

operator whose result is an integer constant), there shall be exactly one external definition
for the identifier in the translation unit.

Semantics

4

As discussed in 5.1.1.1, the unit of program text after preprocessing is a translation unit,
which consists of a sequence of external declarations. These are described as ‘‘external’’
because they appear outside any function (and hence have file scope). As discussed in
6.7, a declaration that also causes storage to be reserved for an object or a function named
by the identifier is a definition.

5

An external definition is an external declaration that is also a definition of a function
(other than an inline definition) or an object. If an identifier declared with external
linkage is used in an expression (other than as part of the operand of a

sizeof

operator

whose result is an integer constant), somewhere in the entire program there shall be
exactly one external definition for the identifier; otherwise, there shall be no more than
one.

140)

140) Thus, if an identifier declared with external linkage is not used in an expression, there need be no

external definition for it.

140 Language

§6.9

6.9.1 Function definitions

Syntax

1

function-definition:

declaration-specifiers declarator declaration-list

opt

compound-statement

declaration-list:

declaration
declaration-list declaration

Constraints

2

The identifier declared in a function definition (which is the name of the function) shall
have a function type, as specified by the declarator portion of the function definition.

141)

3

The return type of a function shall be

void

or an object type other than array type.

4

The storage-class specifier, if any, in the declaration specifiers shall be either

extern

or

static

.

5

If the declarator includes a parameter type list, the declaration of each parameter shall
include an identifier, except for the special case of a parameter list consisting of a single
parameter of type

void

, in which case there shall not be an identifier. No declaration list

shall follow.

6

If the declarator includes an identifier list, each declaration in the declaration list shall
have at least one declarator, those declarators shall declare only identifiers from the
identifier list, and every identifier in the identifier list shall be declared. An identifier
declared as a typedef name shall not be redeclared as a parameter. The declarations in the
declaration list shall contain no storage-class specifier other than

register

and no

initializations.

141) The intent is that the type category in a function definition cannot be inherited from a typedef:

typedef int F(void);

//

type

F

is ‘‘function with no parameters

//

returning

int

’’

F f, g;

// f

and

g

both have type compatible with

F

F f { /*

...

*/ }

//

WRONG: syntax/constraint error

F g() { /*

...

*/ }

//

WRONG: declares that

g

returns a function

int f(void) { /*

...

*/ }

//

RIGHT:

f

has type compatible with

F

int g() { /*

...

*/ }

//

RIGHT:

g

has type compatible with

F

F *e(void) { /*

...

*/ }

// e

returns a pointer to a function

F *((e))(void) { /*

...

*/ }

//

same: parentheses irrelevant

int (*fp)(void);

// fp

points to a function that has type

F

F *Fp; // Fp

points to a function that has type

F

§6.9.1 Language

141

Semantics

7

The declarator in a function definition specifies the name of the function being defined
and the identifiers of its parameters. If the declarator includes a parameter type list, the
list also specifies the types of all the parameters; such a declarator also serves as a
function prototype for later calls to the same function in the same translation unit. If the
declarator includes an identifier list,

142)

the types of the parameters shall be declared in a

following declaration list. In either case, the type of each parameter is adjusted as
described in 6.7.5.3 for a parameter type list; the resulting type shall be an object type.

8

If a function that accepts a variable number of arguments is defined without a parameter
type list that ends with the ellipsis notation, the behavior is undefined.

9

Each parameter has automatic storage duration. Its identifier is an lvalue, which is in
effect declared at the head of the compound statement that constitutes the function body
(and therefore cannot be redeclared in the function body except in an enclosed block).
The layout of the storage for parameters is unspecified.

10

On entry to the function, the size expressions of each variably modified parameter are
evaluated and the value of each argument expression is converted to the type of the
corresponding parameter as if by assignment.

(Array expressions and function

designators as arguments were converted to pointers before the call.)

11

After all parameters have been assigned, the compound statement that constitutes the
body of the function definition is executed.

12

If the

}

that terminates a function is reached, and the value of the function call is used by

the caller, the behavior is undefined.

13

EXAMPLE 1

In the following:

extern int max(int a, int b)

{

return a > b ? a : b;

}

extern

is the storage-class specifier and

int

is the type specifier;

max(int a,

int b)

is the

function declarator; and

{ return a > b ? a : b; }

is the function body. The following similar definition uses the identifier-list form for the parameter
declarations:

142) See ‘‘future language directions’’ (6.11.7).

142 Language

§6.9.1

extern int max(a, b)

int a, b;

{

return a > b ? a : b;

}

Here

int a, b;

is the declaration list for the parameters. The difference between these two definitions is

that the first form acts as a prototype declaration that forces conversion of the arguments of subsequent calls
to the function, whereas the second form does not.

14

EXAMPLE 2

To pass one function to another, one might say

int f(void);

/*

...

*/

g(f);

Then the definition of

g

might read

void g(int (*funcp)(void))

{

/*

...

*/

(*funcp)(); /*

or

funcp();

...

*/

}

or, equivalently,

void g(int func(void))

{

/*

...

*/

func(); /*

or

(*func)();

...

*/

}

6.9.2 External object definitions

Semantics

1

If the declaration of an identifier for an object has file scope and an initializer, the
declaration is an external definition for the identifier.

2

A declaration of an identifier for an object that has file scope without an initializer, and
without a storage-class specifier or with the storage-class specifier

static

, constitutes a

tentative definition. If a translation unit contains one or more tentative definitions for an
identifier, and the translation unit contains no external definition for that identifier, then
the behavior is exactly as if the translation unit contains a file scope declaration of that
identifier, with the composite type as of the end of the translation unit, with an initializer
equal to 0.

3

If the declaration of an identifier for an object is a tentative definition and has internal
linkage, the declared type shall not be an incomplete type.

§6.9.2 Language

143

4

EXAMPLE 1

int i1 = 1;

//

definition, external linkage

static int i2 = 2;

//

definition, internal linkage

extern int i3 = 3;

//

definition, external linkage

int i4;

//

tentative definition, external linkage

static int i5;

//

tentative definition, internal linkage

int i1;

//

valid tentative definition, refers to pre vious

int i2;

//

6.2.2 renders undefined, linkage disagreement

int i3;

//

valid tentative definition, refers to pre vious

int i4;

//

valid tentative definition, refers to pre vious

int i5;

//

6.2.2 renders undefined, linkage disagreement

extern int i1;

//

refers to pre vious, whose linkage is external

extern int i2;

//

refers to pre vious, whose linkage is internal

extern int i3;

//

refers to pre vious, whose linkage is external

extern int i4;

//

refers to pre vious, whose linkage is external

extern int i5;

//

refers to pre vious, whose linkage is internal

5

EXAMPLE 2

If at the end of the translation unit containing

int i[];

the array

i

still has incomplete type, the implicit initializer causes it to have one element, which is set to

zero on program startup.

144 Language

§6.9.2

6.10 Preprocessing directives

Syntax

1

preprocessing-file:

group

opt

group:

group-part
group group-part

group-part:

if-section
control-line
text-line

#

non-directive

if-section:

if-group elif-groups

opt

else-group

opt

endif-line

if-group:

# if

constant-expression new-line group

opt

# ifdef

identifier new-line group

opt

# ifndef

identifier new-line group

opt

elif-groups:

elif-group
elif-groups elif-group

elif-group:

# elif

constant-expression new-line group

opt

else-group:

# else

new-line group

opt

endif-line:

# endif

new-line

§6.10 Language

145

control-line:

# include

pp-tokens new-line

# define

identifier replacement-list new-line

# define

identifier lparen identifier-list

opt

)

replacement-list new-line

# define

identifier lparen

... )

replacement-list new-line

# define

identifier lparen identifier-list

, ... )

replacement-list new-line

# undef

identifier new-line

# line

pp-tokens new-line

# error

pp-tokens

opt

new-line

# pragma

pp-tokens

opt

new-line

#

new-line

text-line:

pp-tokens

opt

new-line

non-directive:

pp-tokens new-line

lparen:

a

(

character not immediately preceded by white-space

replacement-list:

pp-tokens

opt

pp-tokens:

preprocessing-token
pp-tokens preprocessing-token

new-line:

the new-line character

Description

2

preprocessing directive consists of a sequence of preprocessing tokens that satisfies the
following constraints: The first token in the sequence is a

#

preprocessing token that (at

the start of translation phase 4) is either the first character in the source file (optionally
after white space containing no new-line characters) or that follows white space
containing at least one new-line character. The last token in the sequence is the first new-
line character that follows the first token in the sequence.

143)

A new-line character ends

the preprocessing directive even if it occurs within what would otherwise be an

143) Thus, preprocessing directives are commonly called ‘‘lines’’. These ‘‘lines’’ hav e no other syntactic

significance, as all white space is equivalent except in certain situations during preprocessing (see the

#

character string literal creation operator in 6.10.3.2, for example).

146 Language

§6.10

invocation of a function-like macro.

3

A text line shall not begin with a

#

preprocessing token. A non-directive shall not begin

with any of the directive names appearing in the syntax.

4

When in a group that is skipped (6.10.1), the directive syntax is relaxed to allow any
sequence of preprocessing tokens to occur between the directive name and the following
new-line character.

Constraints

5

The only white-space characters that shall appear between preprocessing tokens within a
preprocessing directive (from just after the introducing

#

preprocessing token through

just before the terminating new-line character) are space and horizontal-tab (including
spaces that have replaced comments or possibly other white-space characters in
translation phase 3).

Semantics

6

The implementation can process and skip sections of source files conditionally, include
other source files, and replace macros. These capabilities are called preprocessing,
because conceptually they occur before translation of the resulting translation unit.

7

The preprocessing tokens within a preprocessing directive are not subject to macro
expansion unless otherwise stated.

8

EXAMPLE In:

#define EMPTY

EMPTY # include <file.h>

the sequence of preprocessing tokens on the second line is not a preprocessing directive, because it does not
begin with a

#

at the start of translation phase 4, even though it will do so after the macro

EMPTY

has been

replaced.

6.10.1 Conditional inclusion

Constraints

1

The expression that controls conditional inclusion shall be an integer constant expression
except that: it shall not contain a cast; identifiers (including those lexically identical to
keywords) are interpreted as described below;

144)

and it may contain unary operator

expressions of the form

144) Because the controlling constant expression is evaluated during translation phase 4, all identifiers

either are or are not macro names — there simply are no keywords, enumeration constants, etc.

§6.10.1 Language

147

defined

identifier

or

defined (

identifier

)

which evaluate to 1 if the identifier is currently defined as a macro name (that is, if it is
predefined or if it has been the subject of a

#define

preprocessing directive without an

intervening

#undef

directive with the same subject identifier), 0 if it is not.

2

Each preprocessing token that remains (in the list of preprocessing tokens that will
become the controlling expression) after all macro replacements have occurred shall be in
the lexical form of a token (6.4).

Semantics

3

Preprocessing directives of the forms

# if

constant-expression new-line group

opt

# elif

constant-expression new-line group

opt

check whether the controlling constant expression evaluates to nonzero.

4

Prior to evaluation, macro invocations in the list of preprocessing tokens that will become
the controlling constant expression are replaced (except for those macro names modified
by the

defined

unary operator), just as in normal text. If the token

defined

is

generated as a result of this replacement process or use of the

defined

unary operator

does not match one of the two specified forms prior to macro replacement, the behavior is
undefined. After all replacements due to macro expansion and the

defined

unary

operator have been performed, all remaining identifiers (including those lexically
identical to keywords) are replaced with the pp-number

0

, and then each preprocessing

token is converted into a token. The resulting tokens compose the controlling constant
expression which is evaluated according to the rules of 6.6. For the purposes of this
token conversion and evaluation, all signed integer types and all unsigned integer types
act as if they hav e the same representation as, respectively, the types

intmax_t

and

uintmax_t

defined in the header

<stdint.h>

.

145)

This includes interpreting

character constants, which may involve converting escape sequences into execution
character set members. Whether the numeric value for these character constants matches
the value obtained when an identical character constant occurs in an expression (other
than within a

#if

or

#elif

directive) is implementation-defined.

146)

Also, whether a

single-character character constant may have a neg ative value is implementation-defined.

5

Preprocessing directives of the forms

145) Thus, on an implementation where

INT_MAX

is

0x7FFF

and

UINT_MAX

is

0xFFFF

, the constant

0x8000

is signed and positive within a

#if

expression even though it would be unsigned in

translation phase 7.

148 Language

§6.10.1

# ifdef

identifier new-line group

opt

# ifndef

identifier new-line group

opt

check whether the identifier is or is not currently defined as a macro name. Their
conditions are equivalent to

#if defined

identifier and

#if !defined

identifier

respectively.

6

Each directive’s condition is checked in order. If it evaluates to false (zero), the group
that it controls is skipped: directives are processed only through the name that determines
the directive in order to keep track of the level of nested conditionals; the rest of the
directives’ preprocessing tokens are ignored, as are the other preprocessing tokens in the
group. Only the first group whose control condition evaluates to true (nonzero) is
processed. If none of the conditions evaluates to true, and there is a

#else

directive, the

group controlled by the

#else

is processed; lacking a

#else

directive, all the groups

until the

#endif

are skipped.

147)

Forward references: macro replacement (6.10.3), source file inclusion (6.10.2), largest
integer types (7.18.1.5).

6.10.2 Source file inclusion

Constraints

1

A

#include

directive shall identify a header or source file that can be processed by the

implementation.

Semantics

2

A preprocessing directive of the form

# include <

h-char-sequence

>

new-line

searches a sequence of implementation-defined places for a header identified uniquely by
the specified sequence between the

<

and

>

delimiters, and causes the replacement of that

directive by the entire contents of the header. How the places are specified or the header
identified is implementation-defined.

3

A preprocessing directive of the form

146) Thus, the constant expression in the following

#if

directive and

if

statement is not guaranteed to

evaluate to the same value in these two contexts.

#if 'z' - 'a' == 25

if ('z' - 'a' == 25)

147) As indicated by the syntax, a preprocessing token shall not follow a

#else

or

#endif

directive

before the terminating new-line character. Howev er, comments may appear anywhere in a source file,
including within a preprocessing directive.

§6.10.2 Language

149

# include "

q-char-sequence

"

new-line

causes the replacement of that directive by the entire contents of the source file identified
by the specified sequence between the

"

delimiters. The named source file is searched

for in an implementation-defined manner. If this search is not supported, or if the search
fails, the directive is reprocessed as if it read

# include <

h-char-sequence

>

new-line

with the identical contained sequence (including

>

characters, if any) from the original

directive.

4

A preprocessing directive of the form

# include

pp-tokens new-line

(that does not match one of the two previous forms) is permitted. The preprocessing
tokens after

include

in the directive are processed just as in normal text. (Each

identifier currently defined as a macro name is replaced by its replacement list of
preprocessing tokens.) The directive resulting after all replacements shall match one of
the two previous forms.

148)

The method by which a sequence of preprocessing tokens

between a

<

and a

>

preprocessing token pair or a pair of

"

characters is combined into a

single header name preprocessing token is implementation-defined.

5

The implementation shall provide unique mappings for sequences consisting of one or
more nondigits or digits (6.4.2.1) followed by a period (

.

) and a single nondigit. The

first character shall not be a digit. The implementation may ignore distinctions of
alphabetical case and restrict the mapping to eight significant characters before the
period.

6

A

#include

preprocessing directive may appear in a source file that has been read

because of a

#include

directive in another file, up to an implementation-defined

nesting limit (see 5.2.4.1).

7

EXAMPLE 1

The most common uses of

#include

preprocessing directives are as in the following:

#include <stdio.h>

#include "myprog.h"

8

EXAMPLE 2

This illustrates macro-replaced

#include

directives:

148) Note that adjacent string literals are not concatenated into a single string literal (see the translation

phases in 5.1.1.2); thus, an expansion that results in two string literals is an invalid directive.

150 Language

§6.10.2

#if VERSION == 1

#define INCFILE

"vers1.h"

#elif VERSION == 2

#define INCFILE

"vers2.h" //

and so on

#else

#define INCFILE

"versN.h"

#endif

#include INCFILE

Forward references: macro replacement (6.10.3).

6.10.3 Macro replacement

Constraints

1

Tw o replacement lists are identical if and only if the preprocessing tokens in both have
the same number, ordering, spelling, and white-space separation, where all white-space
separations are considered identical.

2

An identifier currently defined as an object-like macro shall not be redefined by another

#define

preprocessing directive unless the second definition is an object-like macro

definition and the two replacement lists are identical. Likewise, an identifier currently
defined as a function-like macro shall not be redefined by another

#define

preprocessing directive unless the second definition is a function-like macro definition
that has the same number and spelling of parameters, and the two replacement lists are
identical.

3

There shall be white-space between the identifier and the replacement list in the definition
of an object-like macro.

4

If the identifier-list in the macro definition does not end with an ellipsis, the number of
arguments (including those arguments consisting of no preprocessing tokens) in an
invocation of a function-like macro shall equal the number of parameters in the macro
definition. Otherwise, there shall be more arguments in the invocation than there are
parameters in the macro definition (excluding the

...

). There shall exist a

)

preprocessing token that terminates the invocation.

5

The identifier

_ _VA_ARGS_ _

shall occur only in the replacement-list of a function-like

macro that uses the ellipsis notation in the parameters.

6

A parameter identifier in a function-like macro shall be uniquely declared within its
scope.

Semantics

7

The identifier immediately following the

define

is called the macro name. There is one

name space for macro names. Any white-space characters preceding or following the
replacement list of preprocessing tokens are not considered part of the replacement list
for either form of macro.

§6.10.3 Language

151

8

If a

#

preprocessing token, followed by an identifier, occurs lexically at the point at which

a preprocessing directive could begin, the identifier is not subject to macro replacement.

9

A preprocessing directive of the form

# define

identifier replacement-list new-line

defines an object-like macro that causes each subsequent instance of the macro name

149)

to be replaced by the replacement list of preprocessing tokens that constitute the
remainder of the directive. The replacement list is then rescanned for more macro names
as specified below.

10

A preprocessing directive of the form

# define

identifier lparen identifier-list

opt

)

replacement-list new-line

# define

identifier lparen

... )

replacement-list new-line

# define

identifier lparen identifier-list

, ... )

replacement-list new-line

defines a function-like macro with parameters, whose use is similar syntactically to a
function call. The parameters are specified by the optional list of identifiers, whose scope
extends from their declaration in the identifier list until the new-line character that
terminates the

#define

preprocessing directive. Each subsequent instance of the

function-like macro name followed by a

(

as the next preprocessing token introduces the

sequence of preprocessing tokens that is replaced by the replacement list in the definition
(an invocation of the macro). The replaced sequence of preprocessing tokens is
terminated by the matching

)

preprocessing token, skipping intervening matched pairs of

left and right parenthesis preprocessing tokens. Within the sequence of preprocessing
tokens making up an invocation of a function-like macro, new-line is considered a normal
white-space character.

11

The sequence of preprocessing tokens bounded by the outside-most matching parentheses
forms the list of arguments for the function-like macro. The individual arguments within
the list are separated by comma preprocessing tokens, but comma preprocessing tokens
between matching inner parentheses do not separate arguments. If there are sequences of
preprocessing tokens within the list of arguments that would otherwise act as
preprocessing directives,

150)

the behavior is undefined.

12

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

149) Since, by macro-replacement time, all character constants and string literals are preprocessing tokens,

not sequences possibly containing identifier-like subsequences (see 5.1.1.2, translation phases), they
are never scanned for macro names or parameters.

150) Despite the name, a non-directive is a preprocessing directive.

152 Language

§6.10.3

merger, the number of arguments is one more than the number of parameters in the macro
definition (excluding the

...

).

6.10.3.1 Argument substitution

1

After the arguments for the invocation of a function-like macro have been identified,
argument substitution takes place. A parameter in the replacement list, unless preceded
by a

#

or

##

preprocessing token or followed by a

##

preprocessing token (see below), is

replaced by the corresponding argument after all macros contained therein have been
expanded. Before being substituted, each argument’s preprocessing tokens are
completely macro replaced as if they formed the rest of the preprocessing file; no other
preprocessing tokens are available.

2

An identifier

_ _VA_ARGS_ _

that occurs in the replacement list shall be treated as if it

were a parameter, and the variable arguments shall form the preprocessing tokens used to
replace it.

6.10.3.2 The

#

operator

Constraints

1

Each

#

preprocessing token in the replacement list for a function-like macro shall be

followed by a parameter as the next preprocessing token in the replacement list.

Semantics

2

If, in the replacement list, a parameter is immediately preceded by a

#

preprocessing

token, both are replaced by a single character string literal preprocessing token that
contains the spelling of the preprocessing token sequence for the corresponding
argument. Each occurrence of white space between the argument’s preprocessing tokens
becomes a single space character in the character string literal. White space before the
first preprocessing token and after the last preprocessing token composing the argument
is deleted. Otherwise, the original spelling of each preprocessing token in the argument
is retained in the character string literal, except for special handling for producing the
spelling of string literals and character constants: a

\

character is inserted before each

"

and

\

character of a character constant or string literal (including the delimiting

"

characters), except that it is implementation-defined whether a

\

character is inserted

before the

\

character beginning a universal character name. If the replacement that

results is not a valid character string literal, the behavior is undefined. The character
string literal corresponding to an empty argument is

""

. The order of evaluation of

#

and

##

operators is unspecified.

§6.10.3.2 Language

153

6.10.3.3 The

##

operator

Constraints

1

A

##

preprocessing token shall not occur at the beginning or at the end of a replacement

list for either form of macro definition.

Semantics

2

If, in the replacement list of a function-like macro, a parameter is immediately preceded
or followed by a

##

preprocessing token, the parameter is replaced by the corresponding

argument’s preprocessing token sequence; however, if an argument consists of no
preprocessing tokens, the parameter is replaced by a placemarker preprocessing token
instead.

151)

3

For both object-like and function-like macro invocations, before the replacement list is
reexamined for more macro names to replace, each instance of a

##

preprocessing token

in the replacement list (not from an argument) is deleted and the preceding preprocessing
token is concatenated with the following preprocessing token. Placemarker
preprocessing tokens are handled specially: concatenation of two placemarkers results in
a single placemarker preprocessing token, and concatenation of a placemarker with a
non-placemarker preprocessing token results in the non-placemarker preprocessing token.
If the result is not a valid preprocessing token, the behavior is undefined. The resulting
token is available for further macro replacement. The order of evaluation of

##

operators

is unspecified.

4

EXAMPLE In the following fragment:

#define hash_hash # ## #

#define mkstr(a) # a

#define in_between(a) mkstr(a)

#define join(c, d) in_between(c hash_hash d)

char p[] = join(x, y); //

equivalent to

// char p[] = "x ## y";

The expansion produces, at various stages:

join(x, y)

in_between(x hash_hash y)

in_between(x ## y)

mkstr(x ## y)

"x ## y"

In other words, expanding

hash_hash

produces a new token, consisting of two adjacent sharp signs, but

this new token is not the

##

operator.

151) Placemarker preprocessing tokens do not appear in the syntax because they are temporary entities that

exist only within translation phase 4.

154 Language

§6.10.3.3

6.10.3.4 Rescanning and further replacement

1

After all parameters in the replacement list have been substituted and

#

and

##

processing has taken place, all placemarker preprocessing tokens are removed. Then, the
resulting preprocessing token sequence is rescanned, along with all subsequent
preprocessing tokens of the source file, for more macro names to replace.

2

If the name of the macro being replaced is found during this scan of the replacement list
(not including the rest of the source file’s preprocessing tokens), it is not replaced.
Furthermore, if any nested replacements encounter the name of the macro being replaced,
it is not replaced. These nonreplaced macro name preprocessing tokens are no longer
available for further replacement even if they are later (re)examined in contexts in which
that macro name preprocessing token would otherwise have been replaced.

3

The resulting completely macro-replaced preprocessing token sequence is not processed
as a preprocessing directive even if it resembles one, but all pragma unary operator
expressions within it are then processed as specified in 6.10.9 below.

6.10.3.5 Scope of macro definitions

1

A macro definition lasts (independent of block structure) until a corresponding

#undef

directive is encountered or (if none is encountered) until the end of the preprocessing
translation unit. Macro definitions have no significance after translation phase 4.

2

A preprocessing directive of the form

# undef

identifier new-line

causes the specified identifier no longer to be defined as a macro name. It is ignored if
the specified identifier is not currently defined as a macro name.

3

EXAMPLE 1

The simplest use of this facility is to define a ‘‘manifest constant’’, as in

#define TABSIZE 100

int table[TABSIZE];

4

EXAMPLE 2

The following defines a function-like macro whose value is the maximum of its arguments.

It has the advantages of working for any compatible types of the arguments and of generating in-line code
without the overhead of function calling. It has the disadvantages of evaluating one or the other of its
arguments a second time (including side effects) and generating more code than a function if invoked
several times. It also cannot have its address taken, as it has none.

#define max(a, b) ((a) > (b) ? (a) : (b))

The parentheses ensure that the arguments and the resulting expression are bound properly.

§6.10.3.5 Language

155

5

EXAMPLE 3

To illustrate the rules for redefinition and reexamination, the sequence

#define x

3

#define f(a)

f(x * (a))

#undef x

#define x

2

#define g

f

#define z

z[0]

#define h

g(~

#define m(a)

a(w)

#define w

0,1

#define t(a)

a

#define p()

int

#define q(x)

x

#define r(x,y) x ## y

#define str(x) # x

f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);

g(x+(3,4)-w) | h 5) & m

(f)^m(m);

p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) };

char c[2][6] = { str(hello), str() };

results in

f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);

f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);

int i[] = { 1, 23, 4, 5,

};

char c[2][6] = { "hello", "" };

6

EXAMPLE 4

To illustrate the rules for creating character string literals and concatenating tokens, the

sequence

#define str(s)

# s

#define xstr(s)

str(s)

#define debug(s, t) printf("x" # s "= %d, x" # t "= %s", \

x ## s, x ## t)

#define INCFILE(n)

vers ## n

#define glue(a, b)

a ## b

#define xglue(a, b) glue(a, b)

#define HIGHLOW

"hello"

#define LOW

LOW ", world"

debug(1, 2);

fputs(str(strncmp("abc\0d", "abc", '\4') //

this goes away

== 0) str(: @\n), s);

#include xstr(INCFILE(2).h)

glue(HIGH, LOW);

xglue(HIGH, LOW)

results in

156 Language

§6.10.3.5

 

 

 

 

 

 

 

Content      ..     5      6      7      8     ..