.EQ delim $$ .EN .TL .bd 1 3 \!.bd 1 3 \f1The C Programming Language\(emReference Manual\(dg\fP .AU .bd 1 \!.bd 1 Dennis M. Ritchie .AI .MH .SH "1. INTRODUCTION" .PP This manual .FS .ps +1 \(dg This manual is reprinted, with minor changes, from .I "The C Programming Language" by Brian W. Kernighan and Dennis M. Ritchie, Prentice Hall, Inc., 1978. .ps .FE describes the C language on the .UC DEC .UC PDP -11, .if \nv=7 the .if \nv=7 .UC DEC .if \nv=7 .UC VAX -11/780, the Honeywell 6000, the .UC IBM System/370, and the Interdata 8/32. Where differences exist, it concentrates on the .UC PDP -11, but tries to point out implementation-dependent details. With few exceptions, such dependencies follow directly from the properties of the hardware; the various compilers are generally quite compatible. .SH "2. LEXICAL CONVENTIONS" .ix "lexical@conventions .PP There are six classes of tokens: identifiers, keywords, constants, strings, operators, and other separators. Blanks, tabs, new-lines, .ix "comment and comments (collectively, ``white space'') as described below are ignored except as they serve to separate tokens. Some white space is required to separate otherwise adjacent identifiers, keywords, and constants. .ix "program@format .PP If the input stream has been parsed into tokens up to a given character, the next token is taken to include the longest string of characters which could possibly constitute a token. .SH "2.1 Comments" .PP The characters .UL /* introduce a comment, which terminates with the characters .UL */ . Comments do not nest. .SH "2.2 Identifiers (Names)" .PP An identifier is a sequence of letters and digits; the first character must be a letter; the underscore .UL _ counts as a letter. .ix "underscore@character Upper and lower case letters are different. No more than the first eight characters are significant, .ix "external@names,@length@of .ix "length@of names .ix "function@names,@length@of although more may be used. External identifiers, which are used by various assemblers and loaders, are more restricted: .DS .ta 1.5i \s-1DEC PDP\s0-11 7 characters, 2 cases .if \nv=7 \s-1DEC VAX\s0-11 8 characters, 2 cases Honeywell 6000 6 characters, 1 case \s-1IBM\s0 360/370 7 characters, 1 case Interdata 8/32 8 characters, 2 cases .DE .SH "2.3 Keywords" .PP The following identifiers are reserved for use as keywords, and may not be used otherwise: .DS L .TS center; Lf3 Lf3 Lf3 Lf3 . int short goto for char unsigned return do f\&loat auto sizeof while double extern break switch struct register continue case union typedef if default long static else entry .TE .DE .ix "list@of keywords .ix "reserved@words The .UL entry .ix "\f3entry\fR keyword is not currently implemented by any compiler but is reserved for future use. Some implementations also reserve the words .UL fortran .ix "\f3fortran\fR@keyword and .UL asm . .ix "\f3asm\fR@keyword .SH "2.4 Constants" .PP .ix "constants There are several kinds of constants, as listed below. Hardware characteristics that affect sizes are summarized in \(sc2.6. .SH "2.4.1 Integer constants" .PP .ix "integer constant .ix "hexadecimal constant .ix "octal constant An integer constant consisting of a sequence of digits is taken to be octal if it begins with .UL 0 (digit zero), decimal otherwise. The digits .UL 8 and .UL 9 have octal value 10 and 11 respectively. A sequence of digits preceded by .UL 0x or .UL 0X (digit zero) is taken to be a hexadecimal integer. The hexadecimal digits include .UL a or .UL A through .UL f or .UL F with values 10 through 15. A decimal constant whose value exceeds the largest signed machine integer is taken to be .UL long ; an octal or hex constant which exceeds the largest unsigned machine integer is likewise taken to be .UL long . .SH "2.4.2 Explicit long constants" .PP .ix "\f3long\fR constant A decimal, octal, or hexadecimal integer constant immediately followed by .UL l (letter ell) or .UL L is a long constant. As discussed below, on some machines integer and long values may be considered identical. .SH "2.4.3 Character constants" .PP .ix "character constant A character constant is a character enclosed in single quotes, as in .UL 'x' . The value of a character constant is the numerical value of the character in the machine's character set. .PP Certain non-graphic characters, the single quote .UL ' and the backslash .ix "\f3\\\\e\fR backslash@character .ix "\f3\\\\e\fR escape@character .UL \e , may be represented according to the following table of escape sequences: .ix "escape@sequence .DS L .TS center; L L Lf3 . new-line \s-1NL (LF)\s0 \en horizontal tab \s-1HT\s0 \et backspace \s-1BS\s0 \eb carriage return \s-1CR\s0 \er form feed \s-1FF\s0 \ef backslash \f3\e\fR \e\e single quote \f3'\fR \e' bit pattern \fIddd\fR \e\fIddd\fR .TE .DE The escape .UL \e\fIddd\f3 consists of the backslash followed by 1, 2, or 3 octal digits which are taken to specify the value of the desired character. A special case of this construction is .UL \0 (not followed by a digit), which indicates the character .UC NUL . If the character following a backslash is not one of those specified, the backslash is ignored. .SH "2.4.4 Floating constants" .PP .ix "floating constant .ix "\f3double\fR constant A floating constant consists of an integer part, a decimal point, a fraction part, an .UL e or .UL E , and an optionally signed integer exponent. The integer and fraction parts both consist of a sequence of digits. Either the integer part or the fraction part (not both) may be missing; either the decimal point or the .UL e and the exponent (not both) may be missing. Every floating constant is taken to be double-precision. .SH "2.5 Strings" .PP .ix "string@constant .ix "character@string A string is a sequence of characters surrounded by double quotes, as in .UL \&"..." . A string has type ``array of characters'' and storage class .UL static (see \(sc4 below) and is initialized with the given characters. All strings, even when written identically, are distinct. The compiler places a null byte .UL \0 at the end of each string so that programs which scan the string can find its end. In a string, the double quote character .UL \&" must be preceded by a .UL \e ; in addition, the same escapes as described for character constants may be used. Finally, a .UL \e and the immediately following new-line are ignored. .SH "2.6 Hardware characteristics" .PP The following table summarizes certain hardware properties that vary from machine to machine. Although these affect program portability, in practice they are less of a problem than might be thought a priori. .KS .if n .sp .it t .sp .5v .TS center, box, delim($$); c c c c c c c c c c lf3 n n n n. .ft R \s-1DEC PDP\s0-11 Honeywell 6000 \s-1IBM\s0 370 Interdata 8/32 .ps -1 ASCII ASCII EBCDIC ASCII .ps char 8 bits 9 bits 8 bits 8 bits int 16 36 32 32 short 16 36 16 16 long 32 36 32 32 f\&loat 32 36 32 32 double 64 72 64 64 \fRrange\f3 $+-$10$"" sup {+- 38}$ $+-$10$"" sup {+- 38}$ $+-$10$"" sup {+- 76}$ $+-$10$"" sup {+- 76}$ .TE .if n .sp .if t .sp .5v .KE .ix "size@of numbers .\"For these four machines, floating point numbers have 8 bit exponents. .if \nv=7 \{\ The .UC VAX -11 is identical to the .UC PDP -11 except that integers have 32 bits.\ \} .SH "3. SYNTAX NOTATION" .PP .ix "syntax@notation In the syntax notation used in this manual, syntactic categories are indicated by .IT italic type, and literal words and characters in .UL bold type. Alternative categories are listed on separate lines. An optional terminal or non-terminal symbol is indicated by the subscript ``opt,'' so that .SS { \fIexpression\*(op\f3 } .ES indicates an optional expression enclosed in braces. The syntax is summarized in \(sc18. .SH "4. WHAT'S IN A NAME?" .PP C bases the interpretation of an identifier upon two attributes of the identifier: its .IT "storage class" and its .IT type . The storage class determines the location and lifetime of the storage associated with an identifier; the type determines the meaning of the values found in the identifier's storage. .PP There are four declarable storage classes: automatic, static, external, and register. Automatic variables are local to each invocation of a block (\(sc9.2), and are discarded upon exit from the block; static variables are local to a block, but retain their values upon reentry to a block even after control has left the block; external variables exist and retain their values throughout the execution of the entire program, and may be used for communication between functions, even separately compiled functions. Register variables are (if possible) stored in the fast registers of the machine; like automatic variables they are local to each block and disappear on exit from the block. .PP C supports several fundamental types of objects: .ix "fundamental types .PP Objects declared as characters .ix "\f3char\fR type .UL char ) ( are large enough to store any member of the implementation's character set, and if a genuine character from that character set is stored in a character variable, its value is equivalent to the integer code for that character. Other quantities may be stored into character variables, but the implementation is machine-dependent. .ix "signed character .PP Up to three sizes of integer, declared .UL short .UL int , .ix "\f3short\fR type .ix "\f3long\fR type .UL int , and .UL long .UL int , are available. Longer integers provide no less storage than shorter ones, but the implementation may make either short integers, or long integers, or both, equivalent to plain integers. ``Plain'' integers have the natural size suggested by the host machine architecture; the other sizes are provided to meet special needs. .PP Unsigned integers, declared .UL unsigned, .ix "\f3unsigned\fR type obey the laws of arithmetic modulo $2 sup n$ where $n$ is the number of bits in the representation. (On the .UC PDP -11, unsigned long quantities are not supported.) .PP Single-precision floating point .UL float ) ( and double-precision floating point .UL double ) ( may be synonymous in some implementations. .PP Because objects of the foregoing types can usefully be interpreted as numbers, they will be referred to as .IT arithmetic .ix "arithmetic types types. Types .UL char and .UL int of all sizes will collectively be called .IT integral .ix "integral types types. .UL float and .UL double will collectively be called .IT floating .ix "floating types types. .PP Besides the fundamental arithmetic types there is a conceptually infinite class of derived types constructed from the fundamental types in the following ways: .PP .IT arrays .ix "derived types of objects of most types; .IP .IT functions which return objects of a given type; .IP .IT pointers to objects of a given type; .IP .IT structures containing a sequence of objects of various types; .IP .IT unions capable of containing any one of several objects of various types. .LP In general these methods of constructing objects can be applied recursively. .SH "5. OBJECTS AND LVALUES" .PP .ix "lvalue An .IT object is a manipulatable region of storage; an .IT lvalue is an expression referring to an object. An obvious example of an lvalue expression is an identifier. There are operators which yield lvalues: for example, if .UL E is an expression of pointer type, then .UL *E is an lvalue expression referring to the object to which .UL E points. The name ``lvalue'' comes from the assignment expression .UL E1\ =\ E2 in which the left operand .UL E1 must be an lvalue expression. The discussion of each operator below indicates whether it expects lvalue operands and whether it yields an lvalue. .SH "6. CONVERSIONS" .PP A number of operators may, depending on their operands, cause conversion of the value of an operand from one type to another. This section explains the result to be expected from such conversions. \(sc6.6 summarizes the conversions demanded by most ordinary operators; it will be supplemented as required by the discussion of each operator. .SH "6.1 Characters and integers" .PP .ix "character-integer conversion .ix "integer-character conversion A character or a short integer may be used wherever an integer may be used. In all cases the value is converted to an integer. Conversion of a shorter integer to a longer always involves .ix "integer-\f3long\fR conversion sign extension; integers are signed quantities. Whether or not sign-extension occurs for characters is machine dependent, but it is guaranteed that a member of the standard character set is non-negative. Of the machines treated by this manual, only the .UC PDP -11 sign-extends. .ix "negative character On the .UC PDP -11, character variables range in value from \-128 to 127; the characters of the .UC ASCII alphabet are all positive. A character constant specified with an octal escape suffers sign extension and may appear negative; for example, .UL '\e377' has the value .UL -1 . .PP When a longer integer is converted to a shorter or to a .UL char, .ix "\f3long\fR-integer conversion it is truncated on the left; excess bits are simply discarded. .SH "6.2 Float and double" .PP .ix "\f3float\fR-\f3double\fR conversion .ix "\f3double\fR-\f3float\fR conversion All floating arithmetic in C is carried out in double-precision; whenever a .UL float appears in an expression it is lengthened to .UL double by zero-padding its fraction. When a .UL double must be converted to .UL float , for example by an assignment, the .UL double is rounded before truncation to .UL float length. .SH "6.3 Floating and integral" .PP .ix "floating-integer conversion .ix "integer-floating conversion Conversions of floating values to integral type tend to be rather machine-dependent; in particular the direction of truncation of negative numbers varies from machine to machine. The result is undefined if the value will not fit in the space provided. .PP Conversions of integral values to floating type are well behaved. Some loss of precision occurs if the destination lacks sufficient bits. .SH "6.4 Pointers and integers" .PP .ix "pointer-integer conversion An integer or long integer may be added to or subtracted from a pointer; in such a case the first is converted as specified in the discussion of the addition operator. .PP Two pointers to objects of the same type may be subtracted; in this case the result is converted to an integer as specified in the discussion of the subtraction operator. .SH "6.5 Unsigned" .PP .ix "\f3unsigned\fR-integer conversion .ix "integer-\f3unsigned\fR conversion Whenever an unsigned integer and a plain integer are combined, the plain integer is converted to unsigned and the result is unsigned. The value is the least unsigned integer congruent to the signed integer (modulo $2 sup roman wordsize$). In a 2's complement representation, this conversion is conceptual and there is no actual change in the bit pattern. .PP When an unsigned integer is converted to .UL long , the value of the result is the same numerically as that of the unsigned integer. Thus the conversion amounts to padding with zeros on the left. .SH "6.6 Arithmetic conversions" .PP .ix "arithmetic conversions .ix "type@conversion rules A great many operators cause conversions and yield result types in a similar way. This pattern will be called the ``usual arithmetic conversions.'' .if t .sp .5 .IP First, any operands of type .UL char or .UL short are converted to .UL int, and any of type .UL float are converted to .UL double. .IP Then, if either operand is .UL double, the other is converted to .UL double and that is the type of the result. .IP Otherwise, if either operand is .UL long, the other is converted to .UL long and that is the type of the result. .IP Otherwise, if either operand is .UL unsigned, the other is converted to .UL unsigned and that is the type of the result. .IP Otherwise, both operands must be .UL int, and that is the type of the result. .SH "7. EXPRESSIONS" .PP .ix "expression .ix "precedence@of operators The precedence of expression operators is the same as the order of the major subsections of this section, highest precedence first. Thus, for example, the expressions referred to as the operands of .UL + (\(sc7.4) are those expressions defined in \(sc\(sc7.1-7.3. Within each subsection, the operators have the same precedence. Left- or right-associativity is specified .ix "associativity@of operators in each subsection for the operators discussed therein. The precedence and associativity of all the expression operators is summarized in the grammar of \(sc18. .PP Otherwise the order of evaluation of expressions .ix "order@of@evaluation@of expressions .ix "order@of evaluation is undefined. In particular the compiler considers itself free to compute subexpressions in the order it believes most efficient, even if the subexpressions involve side effects. .ix "side@effects The order in which side effects take place is unspecified. Expressions involving a commutative and associative .ix "commutative operators operator .UL * , ( .UL + , .UL & , .UL | , .UL ^ ) may be rearranged arbitrarily, even in the presence of parentheses; to force a particular order of evaluation an explicit temporary must be used. .PP The handling of overflow and divide check in expression evaluation is machine-dependent. All existing implementations of C ignore integer overflows; .ix "overflow treatment of division by 0, and all floating-point exceptions, varies between machines, and is usually adjustable by a library function. .SH "7.1 Primary expressions" .PP .ix "primary expression Primary expressions involving .UL . , .UL -> , subscripting, and function calls group left to right. .SS \fIprimary-expression:\f3 \fIidentifier\f3 \fIconstant\f3 \fIstring\f3 (\fI expression \f3) \fIprimary-expression \f3[\fI expression \f3]\f3 \fIprimary-expression \f3(\fI expression-list\*(op \f3) \fIprimary-lvalue \f3.\fI identifier\f3 .ix "\&\f3.\fR structure@member@operator \fIprimary-expression \f3->\fI identifier\f3 .ix "\f3->\fR structure@pointer@operator .ES .SS \fIexpression-list:\f3 \fIexpression\f3 \fIexpression-list \f3,\fI expression\f3 .ES An identifier is a primary expression, provided it has been suitably declared as discussed below. Its type is specified by its declaration. If the type of the identifier is ``array of .\|.\|.'', however, .ix "conversion@of array@name then the value of the identifier-expression is a pointer to the first object in the array, and the type of the expression is ``pointer to .\|.\|.''. Moreover, an array identifier is not an lvalue expression. Likewise, an identifier which is declared ``function returning .\|.\|.'', .ix "conversion@of function when used except in the function-name position of a call, is converted to ``pointer to function returning .\|.\|.''. .PP A constant is a primary expression. Its type may be .UL int , .UL long , or .UL double depending on its form. Character constants have type .UL int ; floating constants are .UL double . .PP A string is a primary expression. .ix "type@of string Its type is originally ``array of .UL char ''; but following the same rule given above for identifiers, this is modified to ``pointer to .UL char '' and the result is a pointer to the first character in the string. (There is an exception in certain initializers; see \(sc8.6.) .PP A parenthesized expression is a primary expression .ix "parenthesized expression whose type and value are identical to those of the unadorned expression. The presence of parentheses does not affect whether the expression is an lvalue. .PP A primary expression followed by an expression in square brackets is a primary expression. The intuitive meaning is that of a subscript. Usually, the primary expression has type ``pointer to .\|.\|.'', the subscript expression is .UL int , and the type of the result is ``\|.\|.\|.\|''. The expression .UL E1[E2] is identical (by definition) to .UL *((E1)+(E2)) . All the clues needed to understand this notation are contained in this section together with the discussions in \(sc\(sc 7.1, 7.2, and 7.4 on identifiers, .UL * , and .UL + respectively; \(sc14.3 below summarizes the implications. .PP A function call is a primary expression followed by parentheses .ix "function@call@syntax .ix "function@call@semantics .ix "implicit declaration@of function containing a possibly empty, comma-separated list of expressions which constitute the actual arguments to the function. The primary expression must be of type ``function returning .\|.\|.'', and the result of the function call is of type ``\|.\|.\|.\|''. As indicated below, a hitherto unseen identifier followed immediately by a left parenthesis is contextually declared to represent a function returning an integer; thus in the most common case, integer-valued functions need not be declared. .PP Any actual arguments of type .ix "function@argument conversion .UL float are converted to .UL double before the call; any of type .UL char or .UL short are converted to .UL int ; and as usual, array names are converted to pointers. No other conversions are performed automatically; in particular, the compiler does not compare the types of actual arguments with those of formal arguments. If conversion is needed, use a cast; see \(sc7.2, 8.7. .PP In preparing for the call to a function, a copy is made of each actual parameter; thus, all argument-passing in C is strictly by value. .ix "function argument .ix "call@by@value A function may change the values of its formal parameters, but these changes cannot affect the values of the actual parameters. On the other hand, it is possible to pass a pointer on the understanding that the function may change the value of the object to which the pointer points. An array name is a pointer expression. The order of evaluation of arguments is undefined by the language; take note that the various compilers differ. .PP Recursive calls to any .ix "recursion function are permitted. .PP A primary expression followed by a dot followed by an identifier .ix "structure@reference syntax .ix "structure@reference semantics is an expression. The first expression must be an lvalue naming a structure or a union, and the identifier must name a member of the structure or union. The result is an lvalue referring to the named member of the structure or union. .PP A primary expression followed by an arrow (built from a .UL - and a .UL > ) followed by an identifier is an expression. The first expression must be a pointer to a structure or a union and the identifier must name a member of that structure or union. The result is an lvalue referring to the named member of the structure or union to which the pointer expression points. .PP Thus the expression .UL E1->MOS is the same as .UL (*E1).MOS . Structures and unions are discussed in \(sc8.5. The rules given here for the use of structures and unions are not enforced strictly, in order to allow an escape from the typing mechanism. See \(sc14.1. .SH "7.2 Unary operators" .PP Expressions with unary operators group right-to-left. .SS \fIunary-expression:\f3 .ix "unary expression \f3*\fI expression\f3 .ix "\f3*\fR indirection@operator \f3&\fI lvalue\f3 .ix "\f3&\fR address@operator \f3-\fI expression\f3 .ix "\f3-\fR unary@minus@operator \f3!\fI expression\f3 .ix "\f3!\fR logical@negation@operator \f3~\fI expression\f3 .ix "\f3~\fR one's@complement@operator ++\fI lvalue\f3 .ix "\f3++\fR increment@operator \f3--\fI lvalue\f3 .ix "\f3--\fR decrement@operator \fIlvalue \f3++ \fIlvalue \f3-- \f3(\fI type-name \f3)\fI expression\f3 .ix "cast@operator .ix "explicit conversion@operator \f3sizeof\fI expression\f3 .ix "\f3sizeof\fR@operator \f3sizeof (\fI type-name \f3) .ES The unary .UL * operator means .IT indirection : the expression must be a pointer, and the result is an lvalue referring to the object to which the expression points. If the type of the expression is ``pointer to .\|.\|.'', the type of the result is ``\|.\|.\|.\|''. .PP The result of the unary .UL & operator is a pointer to the object referred to by the lvalue. If the type of the lvalue is ``\|.\|.\|.\|'', the type of the result is ``pointer to .\|.\|.''. .PP The result of the unary .UL - operator is the negative of its operand. .ix "\f3-\fR unary@minus@operator The usual arithmetic conversions are performed. The negative of an unsigned quantity is computed by subtracting its value from $2 sup n$, where $n$ is the number of bits in an .UL int . There is no unary .UL + operator. .PP The result of the logical negation operator .UL ! .ix "\f3!\fR logical@negation@operator is 1 if the value of its operand is 0, 0 if the value of its operand is non-zero. The type of the result is .UL int . It is applicable to any arithmetic type or to pointers. .PP The .UL ~ operator yields the one's complement of its operand. .ix "\f3~\fR one's@complement@operator The usual arithmetic conversions are performed. The type of the operand must be integral. .PP The object referred to by the lvalue operand of prefix .UL ++ .ix "\f3++\fR increment@operator .ix "prefix@\f3++\fR@and@\f3--\fR is incremented. The value is the new value of the operand, but is not an lvalue. The expression .UL ++x is equivalent to .UL x+=1 . See the discussions of addition (\(sc7.4) and assignment operators (\(sc7.14) for information on conversions. .PP The lvalue operand of prefix .UL -- .ix "\f3--\fR decrement@operator is decremented analogously to the prefix .UL ++ operator. .PP When postfix .UL ++ .ix "postfix@\f3++\fR@and@\f3--\fR is applied to an lvalue the result is the value of the object referred to by the lvalue. After the result is noted, the object is incremented in the same manner as for the prefix .UL ++ operator. The type of the result is the same as the type of the lvalue expression. .PP When postfix .UL -- is applied to an lvalue the result is the value of the object referred to by the lvalue. After the result is noted, the object is decremented in the manner as for the prefix .UL -- operator. The type of the result is the same as the type of the lvalue expression. .PP An expression preceded by the parenthesized name of a data type causes conversion of the value of the expression to the named type. This construction is called a .IT cast. .ix "cast@operator Type names are described in \(sc8.7. .PP The .UL sizeof operator yields the size, in bytes, of its operand. .ix "byte (A .IT byte is undefined by the language except in terms of the value of .UL sizeof . However, in all existing implementations a byte is the space required to hold a .UL char .) When applied to an array, the result is the total number of bytes in the array. The size is determined from the declarations of the objects in the expression. This expression is semantically an integer constant and may be used anywhere a constant is required. Its major use is in communication with routines like storage allocators and I/O systems. .PP The .UL sizeof operator may also be applied to a parenthesized type name. In that case it yields the size, in bytes, of an object of the indicated type. .PP The construction \f3sizeof(\fItype\|\f3)\fR is taken to be a unit, so the expression \f3sizeof(\fItype\|\f3)-2\fR is the same as \f3(sizeof(\fItype\|\f3))-2\fR. .SH "7.3 Multiplicative operators" .PP .ix "arithmetic operators .ix "multiplicative operators The multiplicative operators .UL * , .UL / , and .UL % group left-to-right. The usual arithmetic conversions are performed. .SS \fImultiplicative-expression:\f3 \fIexpression \f3*\fI expression\f3 .ix "\f3*\fR multiplication@operator \fIexpression \f3/\fI expression\f3 .ix "\f3/\fR division@operator \fIexpression \f3%\fI expression\f3 .ix "\f3%\fR modulus@operator .ES .PP The binary .UL * operator indicates multiplication. The .UL * operator is associative and expressions with several multiplications at the same level may be rearranged by the compiler. .PP The binary .UL / operator indicates division. When positive integers are divided truncation is toward 0, but the form of truncation is machine-dependent if either operand is negative. On all machines covered by this manual, the remainder has the same sign as the dividend. It is always true that .UL (a/b)*b\ +\ a%b is equal to .UL a (if .UL b is not 0). .PP The binary .UL % operator yields the remainder from the division of the first expression by the second. The usual arithmetic conversions are performed. The operands must not be .UL float . .SH "7.4 Additive operators" .PP .ix "additive operators The additive operators .UL + and .UL - group left-to-right. The usual arithmetic conversions are performed. There are some additional type possibilities for each operator. .SS \fIadditive-expression:\f3 \fIexpression \f3+\fI expression\f3 .ix "\f3+\fR addition@operator \fIexpression \f3-\fI expression\f3 .ix "\f3-\fR subtraction@operator .ES The result of the .UL + operator is the sum of the operands. A pointer to an object in an array and a value of any integral type .ix "pointer-integer conversion .ix "integer-pointer conversion .ix "pointer conversion .ix "pointer arithmetic may be added. The latter is in all cases converted to .ix "pointer arithmetic an address offset by multiplying it by the length of the object to which the pointer points. The result is a pointer of the same type as the original pointer, and which points to another object in the same array, appropriately offset from the original object. Thus if .UL P is a pointer to an object in an array, the expression .UL P+1 is a pointer to the next object in the array. .PP No further type combinations are allowed for pointers. .PP The .UL + operator is associative and expressions with several additions at the same level may be rearranged by the compiler. .PP The result of the .UL - operator is the difference of the operands. The usual arithmetic conversions are performed. Additionally, a value of any integral type may be subtracted from a pointer, and then the same conversions as for addition apply. .PP If two pointers to objects of the same type are subtracted, the result is converted (by division by the length of the object) to an .UL int representing the number of objects separating the pointed-to objects. This conversion will in general give unexpected results unless the pointers point to objects in the same array, since pointers, even to objects of the same type, do not necessarily differ by a multiple of the object-length. .SH "7.5 Shift operators" .PP .ix "shift operators The shift operators .UL << and .UL >> group left-to-right. Both perform the usual arithmetic conversions on their operands, each of which must be integral. Then the right operand is converted to .UL int ; the type of the result is that of the left operand. The result is undefined if the right operand is negative, or greater than or equal to the length of the object in bits. .SS \fIshift-expression:\f3 \fIexpression \f3<<\fI expression\f3 .ix "\f3<<\fR left@shift@operator \fIexpression \f3>>\fI expression\f3 .ix "\f3>>\fR right@shift@operator .ES The value of .UL E1<<E2 is .UL E1 (interpreted as a bit pattern) left-shifted .UL E2 bits; vacated bits are 0-filled. The value of .UL E1>>E2 is .UL E1 right-shifted .UL E2 bit positions. The right shift is guaranteed to be logical (0-fill) if .UL E1 is .UL unsigned ; otherwise it may be (and is, on the .UC PDP -11) arithmetic (fill by a copy of the sign bit). .SH "7.6 Relational operators" .PP .ix "relational operators The relational operators group left-to-right, but this fact is not very useful; .UL a<b<c does not mean what it seems to. .SS \fIrelational-expression:\f3 \fIexpression \f3<\fI expression\f3 .ix "\f3<\fR less@than@operator .ix "\f3>\fR greater@than@operator .ix "\f3<=\fR less@than@or@equal@to@operator .ix "\f3>=\fR greater@than@or@equal@to@operator \fIexpression \f3>\fI expression\f3 \fIexpression \f3<=\fI expression\f3 \fIexpression \f3>=\fI expression\f3 .ES The operators .UL < (less than), .UL > (greater than), .UL <= (less than or equal to) and .UL >= (greater than or equal to) all yield 0 if the specified relation is false and 1 if it is true. The type of the result is .UL int . The usual arithmetic conversions are performed. Two pointers may be compared; the result depends on the relative locations in the address space of the pointed-to objects. Pointer comparison is portable only when the pointers point to objects .ix "pointer comparison in the same array. .SH "7.7 Equality operators" .PP .ix "equality operators .SS \fIequality-expression:\f3 \fIexpression \f3==\fI expression\f3 .ix "\f3==\fR equality@operator .ix "\f3!=\fR inequality@operator \fIexpression \f3!=\fI expression\f3 .ES The .UL == (equal to) and the .UL != (not equal to) operators are exactly analogous to the relational operators except for their lower precedence. (Thus .UL a<b\ ==\ c<d is 1 whenever .UL a<b and .UL c<d have the same truth-value). .PP A pointer may be compared to an integer, but the result is machine dependent unless the integer is the constant 0. A pointer to which 0 has been assigned is guaranteed not to point to any object, and will appear to be equal to 0; in conventional usage, such a pointer is considered to be null. .SH "7.8 Bitwise \s-1AND\s0 operator" .PP .ix "bitwise operators .ix "\f3&\fR bitwise@AND@operator .SS \fIand-expression:\f3 \fIexpression \f3&\fI expression\f3 .ES The .UL & operator is associative and expressions involving .UL & may be rearranged. The usual arithmetic conversions are performed; the result is the bitwise .UC AND function of the operands. The operator applies only to integral operands. .SH "7.9 Bitwise exclusive \s-1OR\s0 operator" .PP .ix "\f3^\fR bitwise@exclusive@OR@operator .SS \fIexclusive-or-expression:\f3 \fIexpression \f3^\fI expression\f3 .ES .LP The .UL ^ operator is associative and expressions involving .UL ^ may be rearranged. The usual arithmetic conversions are performed; the result is the bitwise exclusive .UC OR function of the operands. The operator applies only to integral operands. .SH "7.10 Bitwise inclusive \s-1OR\s0 operator" .PP .ix "\f3|\fR bitwise@inclusive@OR@operator .SS \fIinclusive-or-expression:\f3 \fIexpression \f3|\fI expression\f3 .ES The .UL | operator is associative and expressions involving .UL | may be rearranged. The usual arithmetic conversions are performed; the result is the bitwise inclusive .UC OR function of its operands. The operator applies only to integral operands. .SH "7.11 Logical \s-1AND\s0 operator" .PP .ix "\f3&&\fR logical@AND@operator .SS \fIlogical-and-expression:\f3 \fIexpression \f3&&\fI expression\f3 .ES The .UL && operator groups left-to-right. It returns 1 if both its operands are non-zero, 0 otherwise. Unlike .UL & , .UL && guarantees left-to-right evaluation; moreover the second operand is not evaluated if the first operand is 0. .PP The operands need not have the same type, but each must have one of the fundamental types or be a pointer. The result is always .UL int. .SH "7.12 Logical \s-1OR\s0 operator" .ix "\f3||\fR logical@OR@operator .PP .SS \fIlogical-or-expression:\f3 \fIexpression \f3||\fI expression\f3 .ES The .UL || operator groups left-to-right. It returns 1 if either of its operands is non-zero, and 0 otherwise. Unlike .UL | , .UL || guarantees left-to-right evaluation; moreover, the second operand is not evaluated if the value of the first operand is non-zero. .PP The operands need not have the same type, but each must have one of the fundamental types or be a pointer. The result is always .UL int . .SH "7.13 Conditional operator" .PP .ix "\f3?:\fR conditional@expression .SS \fIconditional-expression:\f3 \fIexpression \f3?\fI expression \f3:\fI expression\f3 .ES Conditional expressions group right-to-left. The first expression is evaluated and if it is non-zero, the result is the value of the second expression, otherwise that of third expression. If possible, the usual arithmetic conversions are performed to bring the second and third expressions to a common type; otherwise, if both are pointers of the same type, the result has the common type; otherwise, one must be a pointer and the other the constant 0, and the result has the type of the pointer. Only one of the second and third expressions is evaluated. .SH "7.14 Assignment operators" .PP .ix "assignment operators There are a number of assignment operators, all of which group right-to-left. All require an lvalue as their left operand, and the type of an assignment expression is that .ix "assignment expression of its left operand. The value is the value stored in the left operand after the assignment has taken place. The two parts of a compound assignment operator are separate tokens. .SS \fIassignment-expression:\f3 \fIlvalue \f3=\fI expression\f3 \fIlvalue \f3+=\fI expression\f3 \fIlvalue \f3-=\fI expression\f3 \fIlvalue \f3*=\fI expression\f3 \fIlvalue \f3/=\fI expression\f3 \fIlvalue \f3%=\fI expression\f3 \fIlvalue \f3>>=\fI expression\f3 \fIlvalue \f3<<=\fI expression\f3 \fIlvalue \f3&=\fI expression\f3 \fIlvalue \f3^=\fI expression\f3 \fIlvalue \f3|=\fI expression\f3 .ES .PP In the simple assignment with .UL = , the value of the expression replaces that of the object referred to by the lvalue. If both operands have arithmetic type, the right operand is converted to the type of the left preparatory to the assignment. .ix "conversion@by assignment .PP The behavior of an expression of the form .UL E1\ \fIop\|\f3=\ E2 may be inferred by taking it as equivalent to .UL E1\ =\ E1\ \fIop\|\f3\ (E2) ; however, .UL E1 is evaluated only once. In .UL += and .UL -= , the left operand may be a pointer, in which case the (integral) right operand is converted as explained in \(sc7.4; all right operands and all non-pointer left operands must have arithmetic type. .PP The compilers currently allow a pointer to be assigned to an integer, an integer to a pointer, and a pointer to a pointer of another type. The assignment is a pure copy operation, with no conversion. This usage is nonportable, and may produce pointers which cause addressing exceptions when used. However, it is guaranteed that assignment of the constant 0 to a pointer will produce a null pointer .ix "\f3NULL\fR pointer distinguishable from a pointer to any object. .SH "7.15 Comma operator" .PP .ix "comma@operator .SS \fIcomma-expression:\f3 \fIexpression \f3,\fI expression\f3 .ES A pair of expressions separated by a comma is evaluated left-to-right and the value of the left expression is discarded. The type and value of the result are the type and value of the right operand. This operator groups left-to-right. In contexts where comma is given a special meaning, for example in a list of actual arguments to functions (\(sc7.1) and lists of initializers (\(sc8.6), the comma operator as described in this section can only appear in parentheses; for example, .P1 f(a, (t=3, t+2), c) .P2 has three arguments, the second of which has the value 5. .SH "8. DECLARATIONS" .PP .ix "declarations Declarations are used to specify the interpretation which C gives to each identifier; they do not necessarily reserve storage associated with the identifier. Declarations have the form .SS \fIdeclaration:\f3 \fIdecl-specifiers declarator-list\*(op \f3; .ES The declarators in the declarator-list contain the identifiers being declared. The decl-specifiers consist of a sequence of type and storage class specifiers. .SS \fIdecl-specifiers:\f3 \fItype-specifier decl-specifiers\*(op\f3 \fIsc-specifier decl-specifiers\*(op\f3 .ES The list must be self-consistent in a way described below. .SH "8.1 Storage class specifiers" .PP .ix "storage@class specifier .ix "storage@class declaration The sc-specifiers are: .SS \fIsc-specifier:\f3 auto static extern register typedef .ix "\f3auto\fR storage@class .ix "\f3static\fR storage@class .ix "\f3extern\fR storage@class .ix "\f3register\fR storage@class .ix "\f3typedef\fR declaration .ES The .UL typedef specifier does not reserve storage and is called a ``storage class specifier'' only for syntactic convenience; it is discussed in \(sc8.8. The meanings of the various storage classes were discussed in \(sc4. .PP The .UL auto , .UL static , and .UL register declarations also serve as definitions in that they cause an appropriate amount of storage to be reserved. In the .UL extern case there must be an external definition (\(sc10) for the given identifiers somewhere outside the function in which they are declared. .PP A .UL register declaration is best thought of as an .UL auto declaration, together with a hint to the compiler that the variables declared will be heavily used. Only the first few such declarations are effective. Moreover, only variables of certain types will be stored in registers; on the .UC PDP -11, they are .UL int , .UL char , or pointer. One other restriction applies to register variables: the address-of operator .UL & cannot be applied to them. Smaller, faster programs can be expected if register declarations are used appropriately, but future improvements in code generation may render them unnecessary. .PP At most one sc-specifier may be given in a declaration. If the sc-specifier is missing from a declaration, it .ix "missing storage@class specifier is taken to be .UL auto inside a function, .UL extern outside. Exception: functions are never automatic. .SH "8.2 Type specifiers" .PP .ix "type specifier The type-specifiers are .SS \fItype-specifier:\f3 char short int long unsigned float double \fIstruct-or-union-specifier\f3 \fItypedef-name\f3 .ix "\f3char\fR type .ix "\f3short\fR type .ix "\f3int\fR type .ix "\f3long\fR type .ix "\f3unsigned\fR type .ix "\f3float\fR type .ix "\f3double\fR type .ES The words .UL long , .UL short , and .UL unsigned may be thought of as adjectives; the following combinations are acceptable. .SS short int long int unsigned int long float .ES The meaning of the last is the same as .UL double . Otherwise, at most one type-specifier may be given in a declaration. If the type-specifier is missing from a declaration, it is taken to be .ix "missing type specifier .UL int . .PP Specifiers for structures and unions are discussed in \(sc8.5; declarations with .UL typedef names are discussed in \(sc8.8. .SH "8.3 Declarators" .PP .ix "declarator The declarator-list appearing in a declaration is a comma-separated sequence of declarators, each of which may have an initializer. .SS \fIdeclarator-list:\f3 \fIinit-declarator\f3 \fIinit-declarator \f3,\fI declarator-list\f3 .ES .SS \fIinit-declarator:\f3 \fIdeclarator initializer\*(op\f3 .ES Initializers are discussed in \(sc8.6. The specifiers in the declaration indicate the type and storage class of the objects to which the declarators refer. Declarators have the syntax: .SS \fIdeclarator:\f3 \fIidentifier\f3 \f3(\fI declarator \f3) \f3*\fI declarator\f3 \fIdeclarator \f3() \fIdeclarator \f3[\fI constant-expression\*(op \f3] .ES The grouping is the same as in expressions. .SH "8.4 Meaning of declarators" .PP .ix "type declaration Each declarator is taken to be an assertion that when a construction of the same form as the declarator appears in an expression, it yields an object of the indicated type and storage class. Each declarator contains exactly one identifier; it is this identifier that is declared. .PP If an unadorned identifier appears as a declarator, then it has the type indicated by the specifier heading the declaration. .PP A declarator in parentheses is identical to the unadorned declarator, but the binding of complex declarators may be altered by parentheses. See the examples below. .PP Now imagine a declaration .P1 T D1 .P2 where .UL T is a type-specifier (like .UL int , etc.) and .UL D1 is a declarator. Suppose this declaration makes the identifier have type ``\|.\|.\|.\| .UL T ,'' where the ``\|.\|.\|.\|'' is empty if .UL D1 is just a plain identifier (so that the type of .UL x in .UL int\ x '' `` is just .UL int ). Then if .UL D1 has the form .P1 *D .P2 the type of the contained identifier is ``\|.\|.\|.\| pointer to .UL T .'' .ix "declaration@of pointer .PP If .UL D1 has the form .P1 D() .P2 then the contained identifier has the type ``\|.\|.\|. function returning .UL T .'' .ix "declaration@of function .PP If .UL D1 has the form .P1 D[\fIconstant-expression\f3] .P2 or .P1 D[] .P2 then the contained identifier has type ``\|.\|.\|.\| array of .UL T .'' .ix "array declaration In the first case the constant expression is an expression whose value is determinable at compile time, and whose type is .UL int . (Constant expressions are defined precisely in \(sc15.) When several ``array of'' specifications are adjacent, a multi-dimensional array is created; the constant expressions which specify the bounds of the arrays may be missing only for the first member of the sequence. This elision is useful when the array is external and the actual definition, which allocates storage, is given elsewhere. The first constant-expression may also be omitted when the declarator is followed by initialization. In this case the size is calculated from the number .ix "default array@size of initial elements supplied. .PP An array may be constructed from one of the basic types, from a pointer, from a structure or union, or from another array (to generate a multi-dimensional array). .PP Not all the possibilities allowed by the syntax above are actually permitted. The restrictions are as follows: .ix "restrictions@on types functions may not return arrays, structures, unions or functions, although they may return pointers to such things; there are no arrays of functions, although there may be arrays of pointers to functions. Likewise a structure or union may not contain a function, but it may contain a pointer to a function. .PP As an example, the declaration .P1 int i, *ip, f(), *fip(), (*pfi)(); .P2 declares an integer .UL i , a pointer .UL ip to an integer, a function .UL f returning an integer, a function .UL fip returning a pointer to an integer, and a pointer .UL pfi to a function which returns an integer. It is especially useful to compare the last two. The binding of .UL *fip() is .UL *(fip()) , so that the declaration suggests, and the same construction in an expression requires, the calling of a function .UL fip , and then using indirection through the (pointer) result to yield an integer. In the declarator .UL (*pfi)() , the extra parentheses are necessary, as they are also in an expression, to indicate that indirection through a pointer to a function yields a function, which is then called; it returns an integer. .PP As another example, .P1 float fa[17], *afp[17]; .P2 declares an array of .UL float numbers and an array of pointers to .UL float numbers. Finally, .P1 static int x3d[3][5][7]; .P2 declares a static three-dimensional array of integers, with rank 3\(mu5\(mu7. In complete detail, .UL x3d is an array of three items; each item is an array of five arrays; each of the latter arrays is an array of seven integers. Any of the expressions .UL x3d , .UL x3d[i] , .UL x3d[i][j] , .UL x3d[i][j][k] may reasonably appear in an expression. The first three have type ``array,'' the last has type .UL int . .SH "8.5 Structure and union declarations" .PP .ix "structure declaration .ix "\f3union\fR declaration A structure is an object consisting of a sequence of named members. Each member may have any type. A union is an object which may, at a given time, contain any one of several members. Structure and union specifiers have the same form. .SS \fIstruct-or-union-specifier:\f3 \fIstruct-or-union \f3{\fI struct-decl-list \f3} \fIstruct-or-union identifier \f3{\fI struct-decl-list \f3} \fIstruct-or-union identifier\f3 .ES .SS \fIstruct-or-union:\f3 struct union .ES The struct-decl-list is a sequence of declarations for the members of the structure or union: .SS \fIstruct-decl-list:\f3 \fIstruct-declaration\f3 \fIstruct-declaration struct-decl-list\f3 .ES .SS \fIstruct-declaration:\f3 \fItype-specifier struct-declarator-list \f3; .ES .SS \fIstruct-declarator-list:\f3 \fIstruct-declarator\f3 \fIstruct-declarator \f3,\fI struct-declarator-list\f3 .ES In the usual case, a struct-declarator is just a declarator for a member of a structure or union. A structure member may also consist of a specified number of bits. Such a member is also called a .IT field ; .ix "field declaration .ix "bit@fields its length is set off from the field name by a colon. .SS \fIstruct-declarator:\f3 \fIdeclarator\f3 \fIdeclarator \f3:\fI constant-expression\f3 \f3:\fI constant-expression\f3 .ES Within a structure, the objects declared have addresses which increase as their declarations are read left-to-right. Each non-field member of a structure begins on an addressing boundary appropriate to its type; .ix "field alignment therefore, there may be unnamed holes in a structure. Field members are packed into machine integers; they do not straddle words. A field which does not fit into the space remaining in a word is put into the next word. No field may be wider than a word. Fields are assigned right-to-left on the .UC PDP -11, left-to-right on other machines. .PP A struct-declarator with no declarator, only a colon and a width, indicates an unnamed field useful for padding to conform to externally-imposed layouts. As a special case, an unnamed field with a width of 0 specifies alignment of the next field at a word boundary. The ``next field'' presumably is a field, not an ordinary structure member, because in the latter case the alignment would have been automatic. .PP The language does not restrict the types of things that are declared as fields, but implementations are not required to support any but integer fields. Moreover, even .UL int fields may be considered to be unsigned. On the .UC PDP -11, fields are not signed and have only integer values. In all implementations, there are no arrays of fields, and the address-of operator .UL & may not be applied to them, so that there are no pointers to .ix "restrictions@on fields fields. .PP A union may be thought of as a structure all of whose members begin at offset 0 and whose size is sufficient to contain any of its members. At most one of the members can be stored in a union at any time. .PP A structure or union specifier of the second form, that is, one of .SS \f3struct\fI identifier \f3{\fI struct-decl-list \f3} \f3union\fI identifier \f3{\fI struct-decl-list \f3} .ES declares the identifier to be the .IT "structure tag" .ix "structure tag .ix "union tag (or union tag) of the structure specified by the list. A subsequent declaration may then use the third form of specifier, one of .SS \f3struct\fI identifier\f3 \f3union\fI identifier\f3 .ES Structure tags allow definition of self-referential .ix "self-referential structure structures; they also permit the long part of the declaration to be given once and used several times. It is illegal to declare a structure or union which contains an instance of itself, but a structure or union may contain a pointer to an instance of itself. .PP The names of members and tags may be the same as ordinary variables. .ix "structure member@name However, names of tags and members must be mutually distinct. .PP Two structures may share a common initial sequence of members; that is, the same member may appear in two different structures if it has the same type in both and if all previous members are the same in both. (Actually, the compiler checks only that a name in two different structures has the same type and offset in both, but if preceding members differ the construction is nonportable.) .PP A simple example of a structure declaration is .P1 struct tnode { char tword[20]; int count; struct tnode *left; struct tnode *right; }; .P2 which contains an array of 20 characters, an integer, and two pointers to similar structures. Once this declaration has been given, the declaration .P1 struct tnode s, *sp; .P2 declares .UL s to be a structure of the given sort and .UL sp to be a pointer to a structure of the given sort. With these declarations, the expression .P1 sp->count .P2 refers to the .UL count field of the structure to which .UL sp points; .P1 s\f3.\f3left .P2 refers to the left subtree pointer of the structure .UL s ; and .P1 s.right->tword[0] .P2 refers to the first character of the .UL tword member of the right subtree of .UL s . .SH "8.6 Initialization" .PP .ix "initialization A declarator may specify an initial value for the identifier being declared. The initializer is preceded by .UL = , and consists of an expression or a list of values nested in braces. .SS \fIinitializer:\f3 \f3= \fIexpression\f3 \f3= {\fI initializer-list \f3} \f3= {\fI initializer-list \f3, } .ES .SS \fIinitializer-list:\f3 \fIexpression\f3 \fIinitializer-list \f3,\fI initializer-list\f3 {\fI initializer-list \f3} .ES .PP All the expressions in an initializer for a static or external variable must be constant expressions, which are described in \(sc15, or expressions which reduce to the address of a previously declared variable, possibly offset by a constant expression. Automatic or register variables may be initialized by arbitrary .ix "initialization@of automatics expressions involving constants, and previously declared variables and functions. .PP Static and external variables which are not initialized are .ix "initialization@of statics guaranteed to start off as 0; .ix "default initialization automatic and register variables which are not initialized are guaranteed to start off as garbage. .PP When an initializer applies to a .IT scalar (a pointer or an object of arithmetic type), it consists of a single expression, perhaps in braces. The initial value of the object is taken from the expression; the same conversions as for assignment are performed. .PP When the declared variable is an .IT aggregate .ix "aggregate .ix "array initialization .ix "structure initialization (a structure or array) then the initializer consists of a brace-enclosed, comma-separated list of initializers for the members of the aggregate, written in increasing subscript or member order. If the aggregate contains subaggregates, this rule applies recursively to the members of the aggregate. If there are fewer initializers in the list than there are members of the aggregate, then the aggregate is padded with 0's. It is not permitted to initialize unions or automatic aggregates. .PP Braces may be elided as follows. If the initializer begins with a left brace, then the succeeding comma-separated list of initializers initializes the members of the aggregate; it is erroneous for there to be more initializers than members. If, however, the initializer does not begin with a left brace, then only enough elements from the list are taken to account for the members of the aggregate; any remaining members are left to initialize the next member of the aggregate of which the current aggregate is a part. .PP A final abbreviation allows a .UL char array to be initialized by a string. .ix "character@array initialization In this case successive characters of the string initialize the members of the array. .PP For example, .P1 int x[] = { 1, 3, 5 }; .P2 declares and initializes .UL x as a 1-dimensional array which has three members, since no size was specified and there are three initializers. .P1 float y[4][3] = { { 1, 3, 5 }, { 2, 4, 6 }, { 3, 5, 7 }, }; .P2 is a completely-bracketed initialization: 1, 3, and 5 initialize the first row of the array .UL y[0] , namely .UL y[0][0] , .UL y[0][1] , and .UL y[0][2] . Likewise the next two lines initialize .UL y[1] and .UL y[2] . The initializer ends early and therefore .UL y[3] is initialized with 0. Precisely the same effect could have been achieved by .P1 float y[4][3] = { 1, 3, 5, 2, 4, 6, 3, 5, 7 }; .P2 The initializer for .UL y begins with a left brace, but that for .UL y[0] does not, therefore 3 elements from the list are used. Likewise the next three are taken successively for .UL y[1] and .UL y[2] . Also, .P1 float y[4][3] = { { 1 }, { 2 }, { 3 }, { 4 } }; .P2 initializes the first column of .UL y (regarded as a two-dimensional array) and leaves the rest 0. .PP Finally, .P1 char msg[] = "Syntax error on line %s\n"; .P2 shows a character array whose members are initialized with a string. .SH "8.7 Type names" .PP .ix "type@names In two contexts (to specify type conversions explicitly by means of a cast, .ix "cast@operator and as an argument of .UL sizeof ) it is desired to supply the name of a data type. This is accomplished using a ``type name,'' which in essence is a declaration for an object of that type which omits the name of the object. .SS \fItype-name:\f3 \fItype-specifier abstract-declarator\f3 .ES .SS \fIabstract-declarator:\f3 .ix "abstract declarator \fIempty\f3 \f3(\fI abstract-declarator \f3) \f3*\fI abstract-declarator\f3 \fIabstract-declarator \f3() \fIabstract-declarator \f3[\fI constant-expression\*(op \f3] .ES To avoid ambiguity, in the construction .SS \f3(\fI abstract-declarator \f3) .ES the abstract-declarator is required to be non-empty. Under this restriction, it is possible to identify uniquely the location in the abstract-declarator where the identifier would appear if the construction were a declarator in a declaration. The named type is then the same as the type of the hypothetical identifier. For example, .P1 int int * int *[3] int (*)[3] int *() int (*)() .P2 name respectively the types ``integer,'' ``pointer to integer,'' ``array of 3 pointers to integers,'' ``pointer to an array of 3 integers,'' ``function returning pointer to integer,'' and ``pointer to function returning an integer.'' .SH "8.8 Typedef" .PP .ix "\f3typedef\fR declaration Declarations whose ``storage class'' is .UL typedef do not define storage, but instead define identifiers which can be used later as if they were type keywords naming fundamental or derived types. .SS \fItypedef-name:\f3 \fIidentifier\f3 .ES Within the scope of a declaration involving .UL typedef , each identifier appearing as part of any declarator therein become syntactically equivalent to the type keyword naming the type associated with the identifier in the way described in \(sc8.4. For example, after .P1 typedef int MILES, *KLICKSP; typedef struct { double re, im;} complex; .P2 the constructions .P1 MILES distance; extern KLICKSP metricp; complex z, *zp; .P2 are all legal declarations; the type of .UL distance is .UL int , that of .UL metricp is ``pointer to .UL int ,'' and that of .UL z is the specified structure. .UL zp is a pointer to such a structure. .PP .UL typedef does not introduce brand new types, only synonyms for types which could be specified in another way. Thus in the example above .UL distance is considered to have exactly the same type as any other .UL int object. .SH "9. STATEMENTS" .PP .ix "statements Except as indicated, statements are executed in sequence. .ix "sequencing@of statements .SH "9.1 Expression statement" .PP .ix "expression@statement Most statements are expression statements, which have the form .SS \fIexpression \f3; .ES Usually expression statements are assignments or function calls. .SH "9.2 Compound statement, or block" .PP .ix "compound@statement .ix "block So that several statements can be used where one is expected, the compound statement (also, and equivalently, called ``block'') is provided: .SS \fIcompound-statement:\f3 {\fI declaration-list\*(op statement-list\*(op \f3} .ES .SS \fIdeclaration-list:\f3 \fIdeclaration\f3 \fIdeclaration declaration-list\f3 .ES .SS \fIstatement-list:\f3 \fIstatement\f3 \fIstatement statement-list\f3 .ES If any of the identifiers in the declaration-list were previously declared, the outer declaration is pushed down for the duration of the block, .ix "block@structure after which it resumes its force. .PP Any initializations of .ix "initialization@in blocks .UL auto or .UL register variables are performed each time the block is entered at the top. It is currently possible (but a bad practice) to transfer into a block; in that case the initializations are not performed. Initializations of .UL static variables are performed only once when the program begins execution. Inside a block, .UL extern declarations do not reserve storage so initialization is not permitted. .SH "9.3 Conditional statement" .PP .ix "\f3if\fR-\f3else\fR@statement The two forms of the conditional statement are .SS \f3if (\fI expression \f3)\fI statement\f3 \f3if (\fI expression \f3)\fI statement \f3else\fI statement .ES In both cases the expression is evaluated and if it is non-zero, the first substatement is executed. In the second case the second substatement is executed if the expression is 0. As usual the ``else'' ambiguity is resolved by connecting .ix "\f3if\fR-\f3else\fR ambiguity an .UL else with the last encountered .UL else -less .UL if . .SH "9.4 While statement" .PP .ix "\f3while\fR@statement The .UL while statement has the form .SS \f3while (\fI expression \f3)\fI statement .ES The substatement is executed repeatedly so long as the value of the expression remains non-zero. The test takes place before each execution of the statement. .SH "9.5 Do statement" .PP .ix "\f3do\fR@statement The .UL do statement has the form .SS \f3do\fI statement \f3while (\fI expression \f3) ; .ES The substatement is executed repeatedly until the value of the expression becomes zero. The test takes place after each execution of the statement. .SH "9.6 For statement" .PP .ix "\f3for\fR@statement The .UL for statement has the form .SS \f3for (\fI expression-1\*(op \f3;\fI expression-2\*(op \f3;\fI expression-3\*(op \f3)\fI statement .ES This statement is equivalent to .SS \fIexpression-1 \f3; \f3while (\fIexpression-2\|\f3) { \fIstatement\f3 \fIexpression-3 \f3; } .ES Thus the first expression specifies initialization for the loop; the second specifies a test, made before each iteration, such that the loop is exited when the expression becomes 0; the third expression often specifies an incrementing that is performed after each iteration. .PP Any or all of the expressions may be dropped. A missing .IT expression-2 makes the implied .UL while clause equivalent to .UL while(1) ; other missing expressions are simply dropped from the expansion above. .SH "9.7 Switch statement" .PP .ix "\f3switch\fR@statement The .UL switch statement causes control to be transferred to one of several statements depending on the value of an expression. It has the form .SS \f3switch (\fI expression \f3)\fI statement .ES The usual arithmetic conversion is performed on the expression, but the result must be .UL int . The statement is typically compound. Any statement within the statement may be labeled with one or more case prefixes as follows: .SS \f3case\fI constant-expression \f3: .ix "\f3case\fR@prefix .ES where the constant expression must be .UL int . No two of the case constants in the same switch may have the same value. Constant expressions are precisely defined in \(sc15. .PP There may also be at most one statement prefix of the form .SS \f3default : .ix "\f3default\fR@prefix .ES When the .UL switch statement is executed, its expression is evaluated and compared with each case constant. If one of the case constants is equal to the value of the expression, control is passed to the statement following the matched case prefix. If no case constant matches the expression, and if there is a .UL default prefix, control passes to the prefixed statement. If no case matches and if there is no .UL default then none of the statements in the switch is executed. .PP .UL case and .UL default prefixes in themselves do not alter the flow of control, which continues unimpeded across such prefixes. To exit from a switch, see .UL break , \(sc9.8. .PP Usually the statement that is the subject of a switch is compound. Declarations may appear at the head of this statement, but initializations of automatic or register variables are ineffective. .SH "9.8 Break statement" .PP .ix "\f3break\fR@statement The statement .SS \f3break ; .ES causes termination of the smallest enclosing .UL while , .UL do , .UL for , or .UL switch statement; control passes to the statement following the terminated statement. .SH "9.9 Continue statement" .PP .ix "\f3continue\fR@statement The statement .SS \f3continue ; .ES causes control to pass to the loop-continuation portion of the smallest enclosing .UL while , .UL do , or .UL for statement; that is to the end of the loop. More precisely, in each of the statements .SS .ta 1.5i 3i \f3while (...) { do { for (...) { ... ... ... contin: ; contin: ; contin: ; } } while (...); } .ES a .UL continue is equivalent to .UL goto\ contin . (Following the .UL contin: is a null statement, \(sc9.13.) .SH "9.10 Return statement" .PP .ix "\f3return\fR@statement A function returns to its caller by means of the .UL return statement, which has one of the forms .SS return ; return\fI expression \f3; .ES In the first case the returned value is undefined. In the second case, the value of the expression is returned to the caller .ix "type@conversion@by \f3return\fR of the function. If required, the expression is converted, as if by assignment, to the type of the .ix "conversion@by@\f3return\fR function in which it appears. Flowing off the end of a function is equivalent to a return with no returned value. .SH "9.11 Goto statement" .PP .ix "\f3goto\fR@statement Control may be transferred unconditionally by means of the statement .SS goto\fI identifier \f3; .ES The identifier must be a label (\(sc9.12) located in the current function. .SH "9.12 Labeled statement" .PP .ix "labeled@statement .ix "label Any statement may be preceded by label prefixes of the form .SS \fIidentifier \f3: .ES which serve to declare the identifier as a label. The only use of a label is as a target of a .UL goto . The scope of a label is the current function, excluding any sub-blocks in which the same identifier has been redeclared. See \(sc11. .SH "9.13 Null statement" .PP .ix "null@statement .ix "empty@statement The null statement has the form .SS \f3; .ES A null statement is useful to carry a label just before the .UL } of a compound statement or to supply a null body to a looping statement such as .UL while . .SH "10. EXTERNAL DEFINITIONS" .ix "external definition .PP A C program consists of a sequence of external definitions. An external definition declares an identifier to have storage class .UL extern (by default) or perhaps .UL static , and a specified type. The type-specifier (\(sc8.2) may also be empty, in which case the type is taken to be .UL int . The scope of external definitions persists to the end of the file in which they are declared just as the effect of declarations persists to the end of a block. The syntax of external definitions is the same as that of all declarations, except that only at this level may the code for functions be given. .SH "10.1 External function definitions" .PP .ix "function definition Function definitions have the form .SS \fIfunction-definition:\f3 \fIdecl-specifiers\*(op function-declarator function-body\f3 .ES The only sc-specifiers allowed among the decl-specifiers are .UL extern or .UL static ; see \(sc11.2 for the distinction between them. A function declarator is similar to a declarator for a ``function returning .\|.\|.\|'' except that it lists the formal parameters of .ix "formal parameter the function being defined. .SS \fIfunction-declarator:\f3 \fIdeclarator \f3(\fI parameter-list\*(op \f3) .ES .SS \fIparameter-list:\f3 \fIidentifier\f3 \fIidentifier \f3,\fI parameter-list\f3 .ES The function-body has the form .SS \fIfunction-body:\f3 \fIdeclaration-list compound-statement\f3 .ES The identifiers in the parameter list, and only those identifiers, may be declared in the declaration list. Any identifiers whose type is not given are taken to be .UL int . The only storage class which may be specified is .UL register ; if it is specified, the corresponding actual parameter will be copied, if possible, into a register at the outset of the function. .PP A simple example of a complete function definition is .P1 int max(a, b, c) int a, b, c; { int m; m = (a > b) ? a : b; return((m > c) ? m : c); } .P2 Here .UL int is the type-specifier; .UL max(a,\ b,\ c) is the function-declarator; .UL int\ a,\ b,\ c; is the declaration-list for the formal parameters; .UL {\ ...\ } is the block giving the code for the statement. .PP C converts all .UL float actual parameters to .UL double , so formal parameters declared .UL float have their declaration adjusted to read .UL double . Also, since a reference to an array in any context .ix "array@name@argument (in particular as an actual parameter) is taken to mean a pointer to the first element of the array, declarations of formal parameters declared ``array of .\|.\|.\|'' are adjusted to read ``pointer to .\|.\|.\|''. Finally, because structures, unions and functions cannot be passed to a function, it is useless to declare a formal parameter to be a structure, union or function (pointers to such objects are of course permitted). .SH "10.2 External data definitions" .PP .ix "data@definitions .ix "external@data@definitions An external data definition has the form .SS \fIdata-definition:\f3 \fIdeclaration\f3 .ES The storage class of such data may be .UL extern (which is the default) or .UL static , but not .UL auto or .UL register . .SH "11. SCOPE RULES" .PP .ix "scope rules A C program need not all be compiled at the same time: the source text of the program may be kept in several files, and precompiled .ix "separate compilation routines may be loaded from libraries. Communication among the functions of a program may be carried out both through explicit calls and through manipulation of external data. .PP Therefore, there are two kinds of scope to consider: first, what may be called the .ul lexical scope .ix "lexical@scope of an identifier, which is essentially the region of a program during which it may be used without drawing ``undefined identifier'' diagnostics; and second, the scope associated with external identifiers, which is characterized by the rule that references to the same external identifier are references to the same object. .SH "11.1 Lexical scope" .PP The lexical scope of identifiers declared in external definitions persists from the definition through the end of the source file in which they appear. The lexical scope of identifiers which are formal parameters persists through the function with which they are associated. The lexical scope of identifiers declared at the head of blocks persists until the end of the block. The lexical scope of labels is the whole of the function in which they appear. .PP Because all references to the same external identifier refer to the same object (see \(sc11.2) the compiler checks all declarations of the same external identifier for compatibility; in effect their scope is increased to the whole file in which they appear. .PP In all cases, however, if an identifier is explicitly declared at the head of a block, including the block constituting a function, any declaration of that identifier outside the block is suspended until the end of the block. .PP Remember also (\(sc8.5) that identifiers associated with ordinary variables on the one hand and those associated with structure and union members and tags on the other form two disjoint classes which do not conflict. Members and tags follow the same scope rules as other identifiers. .UL typedef names are in the same class as ordinary identifiers. They may be redeclared in inner blocks, but an explicit type must be given in the inner declaration: .P1 typedef float distance; \&... { auto int distance; ... .P2 The .UL int must be present in the second declaration, or it would be taken to be a declaration with no declarators and type .UL distance *. .FS * It is agreed that the ice is thin here. .FE .SH "11.2 Scope of externals" .PP .ix "scope@of externals If a function refers to an identifier declared to be .UL extern , then somewhere among the files or libraries constituting the complete program there must be an external definition for the identifier. All functions in a given program which refer to the same external identifier refer to the same object, so care must be taken that the type and size specified in the definition are compatible with those specified by each function which references the data. .PP The appearance of the .UL extern keyword in an external definition indicates that storage for the identifiers being declared will be allocated in another file. Thus in a multi-file program, an external data definition without the .UL extern specifier must appear in exactly one of the files. Any other files which wish to give an external definition for the identifier must include the .UL extern in the definition. The identifier can be initialized only in the declaration where storage is allocated. .PP Identifiers declared .UL static at the top level in external definitions are not visible in other files. Functions may be declared .UL static . .SH "12. COMPILER CONTROL LINES" .PP .ix "compiler@control@lines .ix "macro preprocessor The C compiler contains a preprocessor capable of macro substitution, conditional compilation, and inclusion of named files. Lines beginning with .UL # communicate with this preprocessor. These lines have syntax independent of the rest of the language; they may appear anywhere and have effect which lasts (independent of scope) until the end of the source program file. .SH "12.1 Token replacement" .PP .ix "token@replacement A compiler-control line of the form .SS \f3#define\fI identifier token-string .ix "\f3#define\fR .ES (note: no trailing semicolon) causes the preprocessor to replace subsequent instances of the identifier with the given string of tokens. A line of the form .SS \f3#define\fI identifier\f3(\fI identifier \f3, ... ,\fI identifier \f3)\fI token-string .ES where there is no space between the first identifier and the .UL ( , is a macro definition with arguments. Subsequent instances of the first identifier followed by a .UL ( , a sequence of tokens delimited by commas, and a .UL ) are replaced by the token string in the definition. Each occurrence of an identifier mentioned in the formal parameter list of the definition is replaced by the corresponding token string from the call. The actual arguments in the call are token strings separated by commas; however commas in quoted strings or protected by parentheses do not separate arguments. The number of formal and actual parameters must be the same. Text inside a string or a character constant is not subject to replacement. .PP In both forms the replacement string is rescanned for more defined identifiers. In both forms a long definition may be continued on another line by writing .UL \e at the end of the line to be continued. .PP This facility is most valuable for definition of ``manifest constants,'' as in .P1 #define TABSIZE 100 int table[TABSIZE]; .P2 A control line of the form .SS \f3#undef\fI identifier .ix "\f3#undef\fR .ES causes the identifier's preprocessor definition to be forgotten. .SH "12.2 File inclusion" .ix "\f3#include\fR .ix "file@inclusion .PP A compiler control line of the form .SS \f3#include "\fIfilename\|\f3" .ES causes the replacement of that line by the entire contents of the file .IT filename . The named file is searched for first in the directory of the original source file, and then in a sequence of standard places. Alternatively, a control line of the form .SS #include <\fIfilename\|\f3> .ES searches only the standard places, and not the directory of the source file. .PP .UL #include 's may be nested. .SH "12.3 Conditional compilation" .PP .ix "conditional@compilation A compiler control line of the form .SS \f3#if\fI constant-expression .ix "\f3#if\fR .ES checks whether the constant expression (see \(sc15) evaluates to non-zero. A control line of the form .SS \f3#ifdef\fI identifier .ix "\f3#ifdef\fR .ES checks whether the identifier is currently defined in the preprocessor; that is, whether it has been the subject of a .UL #define control line. A control line of the form .SS \f3#ifndef\fI identifier .ix "\f3#ifndef\fR .ES checks whether the identifier is currently undefined in the preprocessor. .PP All three forms are followed by an arbitrary number of lines, possibly containing a control line .SS \f3#else .ix "\f3#else\fR .ES and then by a control line .SS \f3#endif .ix "\f3#endif\fR .ES If the checked condition is true then any lines between .UL #else and .UL #endif are ignored. If the checked condition is false then any lines between the test and an .UL #else or, lacking an .UL #else , the .UL #endif , are ignored. .PP These constructions may be nested. .SH "12.4 Line control" .PP For the benefit of other preprocessors which generate C programs, a line of the form .SS \f3#line\fI constant identifier .ix "\f3#line\fR .ES causes the compiler to believe, for purposes of error diagnostics, that the line number of the next source line is given by the constant and the current input file is named by the identifier. If the identifier is absent the remembered file name does not change. .SH "13. IMPLICIT DECLARATIONS" .PP .ix "implicit declaration It is not always necessary to specify both the storage class and the type of identifiers in a declaration. The storage class is supplied by the context in external definitions and in declarations of formal parameters and structure members. In a declaration inside a function, if a storage class but no type is given, the identifier is assumed to be .UL int ; if a type but no storage class is indicated, the identifier is assumed to be .UL auto . An exception to the latter rule is made for functions, since .UL auto functions are meaningless (C being incapable of compiling code into the stack); if the type of an identifier is ``function returning .\|.\|.\|'', it is implicitly declared to be .UL extern . .PP In an expression, an identifier followed by .UL ( and not already declared is contextually .ix "implicit declaration@of function declared to be ``function returning .UL int ''. .SH "14. TYPES REVISITED" .PP This section summarizes the operations which can be performed on objects of certain types. .SH "14.1 Structures and unions" .PP .ix "restrictions@on structures .ix "restrictions@on unions .ix "operations permitted@on structures .ix "operations permitted@on unions There are only two things that can be done with a structure or union: name one of its members (by means of the .UL . operator); or take its address (by unary .UL & ). Other operations, such as assigning from or to it or passing it as a parameter, draw an error message. In the future, it is expected that these operations, but not necessarily others, will be allowed. .PP \(sc7.1 says that in a direct or indirect structure reference (with .UL . or .UL -> ) the name on the right must be a member of the structure named or pointed to by the expression on the left. To allow an escape from the typing rules, this restriction is not firmly enforced by the compiler. In fact, any lvalue is allowed before .UL . , and that lvalue is then assumed to have the form of the structure of which the name on the right is a member. Also, the expression before a .UL -> is required only to be a pointer or an integer. If a pointer, it is assumed to point to a structure of which the name on the right is a member. If an integer, it is taken to be the absolute address, in machine storage units, of the appropriate structure. .PP Such constructions are non-portable. .SH "14.2 Functions" .PP .ix "operations permitted@on functions There are only two things that can be done with a function: call it, or take its address. If the name of a function appears in an expression not in the function-name position of a call, a pointer to the function is generated. .ix "pointer@to function Thus, to pass one function to another, one might say .P1 int f(); ... g(f); .P2 Then the definition of .UL g might read .P1 g(funcp) int (*funcp)(); { ... (*funcp)(); ... } .P2 Notice that .UL f must be declared explicitly in the calling routine since its appearance in .UL g(f) was not followed by .UL ( . .SH "14.3 Arrays, pointers, and subscripting" .PP .ix "array,@explanation@of@subscripting .ix "subscripting,@explanation@of Every time an identifier of array type appears in an expression, it is converted into a pointer to the first member of the array. Because of this conversion, arrays are not lvalues. By definition, the subscript operator .UL [] is interpreted in such a way that .UL E1[E2] is identical to .UL *((E1)+(E2)) . Because of the conversion rules which apply to .UL + , if .UL E1 is an array and .UL E2 an integer, then .UL E1[E2] refers to the .UL E2 -th member of .UL E1 . Therefore, despite its asymmetric appearance, subscripting is a commutative operation. .PP A consistent rule is followed in the case of multi-dimensional arrays. .ix "multi-dimensional array If .UL E is an .IT n -dimensional array of rank $i times j times ... times k$, then .UL E appearing in an expression is converted to a pointer to an $(n-1)$-dimensional array with rank $j times ... times k$. If the .UL * operator, either explicitly or implicitly as a result of subscripting, is applied to this pointer, the result is the pointed-to $(n-1)$-dimensional array, which itself is immediately converted into a pointer. .PP For example, consider .P1 int x[3][5]; .P2 Here .UL x is a 3\(mu5 array of integers. When .UL x appears in an expression, it is converted to a pointer to (the first of three) 5-membered arrays of integers. In the expression .UL x[i] , which is equivalent to .UL *(x+i) , .UL x is first converted to a pointer as described; then .UL i is converted to the type of .UL x , which involves multiplying .UL i by the length the object to which the pointer points, namely 5 integer objects. The results are added and indirection applied to yield an array (of 5 integers) which in turn is converted to a pointer to the first of the integers. If there is another subscript the same argument applies again; this time the result is an integer. .PP It follows from all this that arrays in C are stored row-wise (last subscript varies fastest) .ix "storage@order@of array and that the first subscript in the declaration helps determine the amount of storage consumed by an array but plays no other part in subscript calculations. .SH "14.4 Explicit pointer conversions" .PP .ix "pointer conversion .ix "explicit conversion@operator Certain conversions involving pointers are permitted but have implementation-dependent aspects. They are all specified by means of an explicit type-conversion operator, \(sc\(sc7.2 and 8.7. .PP A pointer may be converted to any of the integral types large .ix "pointer-integer conversion enough to hold it. Whether an .UL int or .UL long is required is machine dependent. The mapping function is also machine dependent, but is intended to be unsurprising to those who know the addressing structure of the machine. Details for some particular machines are given below. .PP An object of integral type may be explicitly converted to a pointer. .ix "integer-pointer conversion The mapping always carries an integer converted from a pointer back to the same pointer, but is otherwise machine dependent. .PP A pointer to one type may be converted to a pointer to another type. The resulting pointer may cause addressing exceptions upon use if the subject pointer does not refer to an object suitably aligned in storage. .ix "alignment@restriction It is guaranteed that a pointer to an object of a given size may be converted to a pointer to an object of a smaller size and back again without change. .PP For example, a storage-allocation routine might accept a size (in bytes) of an object to allocate, and return a .ix "storage allocator .UL char pointer; it might be used in this way. .P1 extern char *alloc(); double *dp; dp = (double *) alloc(sizeof(double)); *dp = 22.0 / 7.0; .P2 .UL alloc must ensure (in a machine-dependent way) that its return value is suitable for conversion to a pointer to .UL double ; then the .IT use of the function is portable. .PP The pointer representation on the .UC PDP -11 corresponds to a 16-bit integer and is measured in bytes. .UL char s have no alignment requirements; everything else must have an even address. .PP On the Honeywell 6000, a pointer corresponds to a 36-bit integer; the word part is in the left 18 bits, and the two bits that select the character in a word just to their right. Thus .UL char pointers are measured in units of $2 sup 16$ bytes; everything else is measured in units of $2 sup 18$ machine words. .UL double quantities and aggregates containing them must lie on an even word address (0 mod $2 sup 19$). .PP The .UC IBM 370 and the Interdata 8/32 are similar. On both, addresses are measured in bytes; elementary objects must be aligned on a boundary equal to their length, so pointers to .UL short must be 0 mod 2, to .UL int and .UL float 0 mod 4, and to .UL double 0 mod 8. Aggregates are aligned on the strictest boundary required by any of their constituents. .SH "15. CONSTANT EXPRESSIONS" .PP .ix "constant expression .ix "permitted@form@of initializer In several places C requires expressions which evaluate to a constant: after .UL case , as array bounds, and in initializers. In the first two cases, the expression can involve only integer constants, character constants, and .UL sizeof expressions, possibly connected by the binary operators .P1 + - * / % & | ^ << >> == != < > <= >= .P2 or by the unary operators .P1 - ~ .P2 or by the ternary operator .P1 ?: .P2 Parentheses can be used for grouping, but not for function calls. .PP More latitude is permitted for initializers; besides constant expressions as discussed above, one can also apply the unary .UL & operator to external or static objects, and to external or static arrays subscripted with a constant expression. The unary .UL & can also be applied implicitly by appearance of unsubscripted arrays and functions. The basic rule is that initializers must evaluate either to a constant or to the address of a previously declared external or static object plus or minus a constant. .SH "16. PORTABILITY CONSIDERATIONS" .PP Certain parts of C are inherently machine dependent. The following list of potential trouble spots is not meant to be all-inclusive, but to point out the main ones. .PP Purely hardware issues like word size and the properties of floating point arithmetic and integer division .ix "division,@integer .ix "machine@dependency .ix "portability have proven in practice to be not much of a problem. Other facets of the hardware are reflected in differing implementations. Some of these, particularly sign extension .ix "sign@extension (converting a negative character into a negative integer) and the order in which bytes are placed in a word, are a nuisance that must be carefully watched. Most of the others are only minor problems. .PP The number of .UL register .ix "restrictions@on@registers variables that can actually be placed in registers varies from machine to machine, as does the set of valid types. Nonetheless, the compilers all do things properly for their own machine; excess or invalid .UL register declarations are ignored. .PP Some difficulties arise only when dubious coding practices are used. It is exceedingly unwise to write programs that depend on any of these properties. .PP The order of evaluation of function arguments .ix "order@of evaluation is not specified by the language. It is right to left on the .UC PDP -11, .if \nv=7 and .if \nv=7 .UC VAX -11, left to right on the others. The order in which side effects take place is also unspecified. .PP Since character constants are really objects of type .UL int , multi-character character constants may be permitted. The specific implementation is very machine dependent, however, because the order in which characters are assigned to a word varies from one machine to another. .PP Fields are assigned to words and characters to integers right-to-left on the .UC PDP -11 .if \nv=7 and .if \nv=7 .UC VAX -11 and left-to-right on other machines. These differences are invisible to isolated programs which do not indulge in type punning (for example, by converting an .UL int pointer to a .UL char pointer and inspecting the pointed-to storage), but must be accounted for when conforming to externally-imposed storage layouts. .PP The language accepted by the various compilers differs in minor details. Most notably, the current .UC PDP -11 compiler will not initialize structures containing bit-fields, and does not accept a few assignment operators in certain contexts where the value of the assignment is used. .SH "17. ANACHRONISMS" .PP .ix "anachronisms Since C is an evolving language, certain obsolete constructions may be found in older programs. Although most versions of the compiler support such anachronisms, ultimately they will disappear, leaving only a portability problem behind. .PP Earlier versions of C used the form .IT =op instead of .IT op= for assignment operators. This leads to ambiguities, typified by .P1 x=-1 .P2 which actually decrements .UL x since the .UL = and the .UL - are adjacent, but which might easily be intended to assign .UL -1 to .UL x. .PP The syntax of initializers has changed: previously, the equals sign that introduces an initializer was not present, so instead of .P1 int x = 1; .P2 one used .P1 int x 1; .P2 The change was made because the initialization .P1 int f (1+2) .P2 resembles a function declaration closely enough to confuse the compilers. .bp .SH "18. SYNTAX SUMMARY" .PP This summary of C syntax is intended more for aiding comprehension than as an exact statement of the language. .ix "syntax@summary .SH "18.1 Expressions" .PP The basic expressions are: .SS \fIexpression:\f3 \fIprimary\f3 *\fI expression\f3 \f3&\fI expression\f3 \f3-\fI expression\f3 \f3!\fI expression\f3 \f3~\fI expression\f3 \f3++\fI lvalue\f3 --\fI lvalue\f3 \fIlvalue \f3++ \fIlvalue \f3-- \f3sizeof\fI expression\f3 \f3(\fI type-name \f3)\fI expression\f3 \fIexpression binop expression\f3 \fIexpression \f3?\fI expression \f3:\fI expression\f3 \fIlvalue asgnop expression\f3 \fIexpression \f3,\fI expression\f3 .ES .SS \fIprimary:\f3 \fIidentifier\f3 \fIconstant\f3 \fIstring\f3 \f3(\fI expression \f3) \fIprimary \f3(\fI expression-list\*(op \f3) \fIprimary \f3[\fI expression \f3] \fIlvalue \f3.\fI identifier\f3 \fIprimary \f3->\fI identifier\f3 .ES .SS \fIlvalue:\f3 \fIidentifier\f3 \fIprimary \f3[\fI expression \f3] \fIlvalue \f3.\fI identifier\f3 \fIprimary \f3->\fI identifier\f3 *\fI expression\f3 \f3(\fI lvalue \f3) .ES .PP The primary-expression operators .SS () [] . -> .ES have highest priority and group left-to-right. The unary operators .P1 * & - ! ~ ++ -- sizeof (\fI type-name \f3) .P2 have priority below the primary operators but higher than any binary operator, and group right-to-left. Binary operators group left-to-right; they have priority decreasing as indicated below. The conditional operator groups right to left. .ix "precedence@of operators .SS \fIbinop:\f3 * / % + - >> << < > <= >= == != & ^ | && || ?: .ES Assignment operators all have the same priority, and all group right-to-left. .SS \fIasgnop:\f3 = += -= *= /= %= >>= <<= &= ^= |= .ES The comma operator has the lowest priority, and groups left-to-right. .SH "18.2 Declarations" .PP .SS \fIdeclaration:\f3 \fIdecl-specifiers init-declarator-list\*(op \f3; .ES .SS \fIdecl-specifiers:\f3 \fItype-specifier decl-specifiers\*(op\f3 \fIsc-specifier decl-specifiers\*(op\f3 .ES .SS \fIsc-specifier:\f3 auto static extern register typedef .ES .SS \fItype-specifier:\f3 char short int long unsigned float double \fIstruct-or-union-specifier\f3 \fItypedef-name\f3 .ES .SS \fIinit-declarator-list:\f3 \fIinit-declarator\f3 \fIinit-declarator \f3,\fI init-declarator-list\f3 .ES .SS \fIinit-declarator:\f3 \fIdeclarator initializer\*(op\f3 .ES .SS \fIdeclarator:\f3 \fIidentifier\f3 \f3(\fI declarator \f3) \f3*\fI declarator\f3 \fIdeclarator \f3() \fIdeclarator \f3[\fI constant-expression\*(op \f3] .ES .SS \fIstruct-or-union-specifier:\f3 \f3struct {\fI struct-decl-list \f3} \f3struct\fI identifier \f3{\fI struct-decl-list \f3} \f3struct\fI identifier\f3 \f3union {\fI struct-decl-list \f3} \f3union\fI identifier \f3{\fI struct-decl-list \f3} \f3union\fI identifier\f3 .ES .SS \fIstruct-decl-list:\f3 \fIstruct-declaration\f3 \fIstruct-declaration struct-decl-list\f3 .ES .SS \fIstruct-declaration:\f3 \fItype-specifier struct-declarator-list \f3; .ES .SS \fIstruct-declarator-list:\f3 \fIstruct-declarator\f3 \fIstruct-declarator \f3,\fI struct-declarator-list\f3 .ES .SS \fIstruct-declarator:\f3 \fIdeclarator\f3 \fIdeclarator \f3:\fI constant-expression\f3 \f3:\fI constant-expression\f3 .ES .SS \fIinitializer:\f3 \f3=\fI expression\f3 \f3= {\fI initializer-list \f3} \f3= {\fI initializer-list \f3, } .ES .SS \fIinitializer-list:\f3 \fIexpression\f3 \fIinitializer-list \f3,\fI initializer-list\f3 {\fI initializer-list \f3} .ES .SS \fItype-name:\f3 \fItype-specifier abstract-declarator\f3 .ES .SS \fIabstract-declarator:\f3 \fIempty\f3 \f3(\fI abstract-declarator \f3) \f3*\fI abstract-declarator\f3 \fIabstract-declarator \f3() \fIabstract-declarator \f3[\fI constant-expression\*(op \f3] .ES .SS \fItypedef-name:\f3 \fIidentifier\f3 .ES .SH "18.3 Statements" .PP .SS \fIcompound-statement:\f3 {\fI declaration-list\*(op statement-list\*(op \f3} .ES .SS \fIdeclaration-list:\f3 \fIdeclaration\f3 \fIdeclaration declaration-list\f3 .ES .SS \fIstatement-list:\f3 \fIstatement\f3 \fIstatement statement-list\f3 .ES .SS \fIstatement:\f3 \fIcompound-statement\f3 \fIexpression \f3; \f3if (\fI expression \f3)\fI statement\f3 \f3if (\fI expression \f3)\fI statement \f3else\fI statement\f3 \f3while (\fI expression \f3)\fI statement\f3 \f3do\fI statement \f3while (\fI expression \f3) ; \f3for (\fI expression-1\*(op \f3;\fI expression-2\*(op \f3;\fI expression-3\*(op \f3)\fI statement\f3 \f3switch (\fI expression \f3)\fI statement\f3 \f3case\fI constant-expression \f3: \fIstatement\f3 \f3default :\fI statement\f3 \f3break ; \f3continue ; return ; return\fI expression \f3; goto\fI identifier \f3; \fIidentifier \f3:\fI statement\f3 \f3; .ES .SH "18.4 External definitions" .PP .SS \fIprogram:\f3 \fIexternal-definition\f3 \fIexternal-definition program\f3 .ES .SS \fIexternal-definition:\f3 \fIfunction-definition\f3 \fIdata-definition\f3 .ES .SS \fIfunction-definition:\f3 \fItype-specifier\*(op\fI function-declarator function-body\f3 .ES .SS \fIfunction-declarator:\f3 \fIdeclarator \f3(\fI parameter-list\*(op \f3) .ES .SS \fIparameter-list:\f3 \fIidentifier\f3 \fIidentifier \f3,\fI parameter-list\f3 .ES .SS \fIfunction-body:\f3 \fItype-decl-list function-statement\f3 .ES .SS \fIfunction-statement:\f3 {\fI declaration-list\*(op statement-list \f3} .ES .SS \fIdata-definition:\f3 \f3extern\fI\*(op type-specifier\*(op init-declarator-list\*(op \f3; \f3static\fI\*(op type-specifier\*(op init-declarator-list\*(op \f3; .ES .bp .SH "18.5 Preprocessor" .LP .SS \f3#define\fI identifier token-string\f3 \f3#define\fI identifier\f3(\fI identifier \f3, ... ,\fI identifier \f3)\fI token-string\f3 \f3#undef\fI identifier\f3 \f3#include "\fIfilename\|\f3" #include <\fIfilename\|\f3> \f3#if\fI constant-expression\f3 \f3#ifdef\fI identifier\f3 \f3#ifndef\fI identifier\f3 \f3#else \f3#endif \f3#line\fI constant identifier .ES .bp .LP .ce .ps 12 Recent Changes to C .sp .ps 10 .ce .ft I November 15, 1978 .ft .sp 2 .PP A few extensions have been made to the C language beyond what is described in the book .I "The C Programming Language" by Brian W. Kernighan and Dennis M. Ritchie, Prentice Hall, Inc., 1978. .SH "1. STRUCTURE ASSIGNMENT" .PP Structures may be assigned, passed as arguments to functions, and returned by functions. The types of operands taking part must be the same. Other plausible operators, such as equality comparison, have not been implemented. .PP There is a subtle defect in the .UC PDP-11 implementation of functions that return structures: if an interrupt occurs during the return sequence, and the same function is called reentrantly during the interrupt, the value returned from the first call may be corrupted. The problem can occur only in the presence of true interrupts, as in an operating system or a user program that makes significant use of signals; ordinary recursive calls are quite safe. .SH "2. ENUMERATION TYPE" .PP There is a new data type analogous to the scalar types of Pascal. To the type-specifiers in the syntax on p. 193 of the C book add .SS \fIenum-specifier .ES with syntax .SS \fIenum-specifier:\f3 \f3enum { \fIenum-list \f3} \f3enum \fIidentifier \f3{ \fIenum-list \f3} \f3enum \fIidentifier \f3 .ES .SS \fIenum-list:\f3 \fIenumerator\f3 \fIenum-list \f3, \fIenumerator\f3 \fIenumerator:\f3 \fIidentifier\f3 \fIidentifier \f3=\fI constant-expression\f3 .ES The role of the identifier in the enum-specifier is entirely analogous to that of the structure tag in a struct-specifier; it names a particular enumeration. For example, .P1 enum color { chartreuse, burgundy, claret, puce }; ... enum color *cp, col; .P2 makes .UL color the enumeration-tag of a type describing various colors, and then declares .UL cp as a pointer to an object of that type, and .UL col as an object of that type. .PP The identifiers in the enum-list are declared as constants, and may appear wherever constants are required. If no enumerators with .UL = appear, then the values of the constants begin at 0 and increase by 1 as the declaration is read from left to right. An enumerator with .UL = gives the associated identifier the value indicated; subsequent identifiers continue the progression from the assigned value. .PP Enumeration tags and constants must all be distinct, and, unlike structure tags and members, are drawn from the same set as ordinary identifiers. .PP Objects of a given enumeration type are regarded as having a type distinct from objects of all other types, and .IT lint flags type mismatches. In the .UC PDP-11 implementation all enumeration variables are treated as if they were .UL int . .sp .I "May 1979"