.\" %sccs.include.proprietary.man%
.\" @(#)Clang.ms 6.4 (Berkeley) %G%
The C Programming Language - Reference Manual
This manual is a reprint, with updates to the current C standard, from
\fIThe C Programming Language\fR,
by Brian W. Kernighan and Dennis M. Richie, Prentice-Hall, Inc., 1978.
.EH 'PSD:6-%''The C Programming Language - Reference Manual'
.OH 'The C Programming Language - Reference Manual''PSD:6-%'
This manual describes the C language on the DEC PDP-11\(dg, the DEC VAX-11,
\(dg DEC PDP-11, and DEC VAX-11 are trademarks of Digital Equipment Corporation.
\(dd 3B 20 is a trademark of AT&T.
Where differences exist, it concentrates on the VAX, but tries to point
out implementation-dependent details. With few execptions, these dependencies
follow directly from the underlying properties of the hardware; the various
compilers are generally quite compatible.
There are six classes of tokens\ -\
identifiers, keywords, constants, strings, operators, and other separators.
Blanks, tabs, new\(hylines,
and comments (collectively, ``white space'') as described below
are ignored except as they serve to separate
Some white space is required to separate
otherwise adjacent identifiers,
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.
introduce a comment which terminates
An identifier is a sequence of letters and digits.
The first character must be a letter.
Uppercase and lowercase letters
Although there is no limit on the length of a name,
only initial characters are significant: at least
eight characters of a non-external name, and perhaps
fewer for external names.
Moreover, some implementations may collapse case
distinctions for external names.
The external name sizes include:
PDP-11 7 characters, 2 cases
VAX-11 >100 characters, 2 cases
AT&T 3B 20 >100 characters, 2 cases
The following identifiers are reserved for use
as keywords and may not be used otherwise:
.ta 0.8i 1.6i 2.4i 3.2i 4.0i
\fBauto do for return typedef
break double goto short union
case else if sizeof unsigned
char enum int static void
continue external long struct while
default float register switch\fR
Some implementations also reserve the words
fortran, asm, gfloat, hfloat
Each has a type; an introduction to types is given in ``NAMES.''
Hardware characteristics that affect sizes are summarized in
``Hardware Characteristics'' under ``LEXICAL CONVENTIONS.''
An integer constant consisting of a sequence of digits
to be octal if it begins with
An octal constant consists of the digits \fB0\fR through \fB7\fR only.
A sequence of digits preceded by
(digit zero) is taken to be a hexadecimal integer.
The hexadecimal digits include
with values 10 through 15.
Otherwise, the integer constant is taken to be decimal.
A decimal constant whose value exceeds the largest
signed machine integer is taken to be
an octal or hex constant which exceeds the largest unsigned machine integer
Otherwise, integer constants are \fBint\fR.
A decimal, octal, or hexadecimal integer constant immediately followed
integer and long values may be considered identical.
A character constant is a character enclosed in single quotes,
The value of a character constant is the numerical value of the
character in the machine's character set.
Certain nongraphic characters,
may be represented according to the following table
bit pattern \fIddd\fR\^ \e\fIddd\fR\^
consists of the backslash followed by 1, 2, or 3 octal digits
which are taken to specify the value of the
A special case of this construction is
by a digit), which indicates the character
If the character following a backslash is not one
A new-line character is illegal in a character constant.
The type of a character constant is \fBint\fR.
A floating constant consists of
an integer part, a decimal point, a fraction part,
and an optionally signed integer exponent.
The integer and fraction parts both consist of a sequence
Either the integer part or the fraction
part (not both) may be missing.
Either the decimal point or
and the exponent (not both) may be missing.
Every floating constant has type \fBdouble\fR.
Names declared as enumerators
(see ``Structure, Union, and Enumeration Declarations'' under
A string is a sequence of characters surrounded by
``array of \fBchar\fR'' and storage class
at the end of each string so that programs
which scan the string can
In a string, the double quote character
in addition, the same escapes as described for character
the immediately following new\(hyline are ignored.
All strings, even when written identically, are distinct.
The following figure summarize
certain hardware properties that vary from machine to machine.
l | l1 lp8 | l1 lp8 | l1 lp8.
DEC PDP\-11 DEC VAX-11 AT&T 3B
float range \(+-10 \(+-38 \(+-10 \(+-38 \(+-10 \(+-38
double range \(+-10 \(+-38 \(+-10 \(+-38 \(+-10 \(+-308
.FG 4 4 1 "DEC PDP-11 HARDWARE CHARACTERISTICS"
Syntactic categories are indicated by
and literal words and characters
Alternative categories are listed on separate lines.
An optional terminal or nonterminal symbol is
indicated by the subscript ``opt,'' so that
{ \fIexpression\v'0.5'\s-2opt\s0\v'-0.5'\fR }
indicates an optional expression enclosed in braces.
The syntax is summarized in ``SYNTAX SUMMARY''.
The C language bases the interpretation of an
identifier upon two attributes of the identifier \(mi its
The storage class determines the location and lifetime
of the storage associated with an identifier;
the meaning of the values
found in the identifier's storage.
There are four declarable storage classes:
Automatic variables are local to each invocation of
a block (see ``Compound Statement or Block'' in
``STATEMENTS'') 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
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.
The C language supports several
Objects declared as characters
are large enough to store any member of the implementation's
If a genuine character from that character set is
stored in a \fBchar\fR 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.
In particular, \fBchar\fR may be signed or unsigned by default.
Up to three sizes of integer, declared
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.
The properties of \fBenum\fR types (see ``Structure, Union, and Enumeration Declarations''
are identical to those of
The implementation may use the range of values to
determine how to allocate storage.
obey the laws of arithmetic modulo
where \fIn\fR is the number of bits in the representation.
unsigned long quantities are not supported.)
Single-precision floating point
and double precision floating point
may be synonymous in some implementations.
Because objects of the foregoing types can usefully be interpreted
as numbers, they will be referred to as
of all sizes whether \fBunsigned\fR or not, and
will collectively be called
types will collectively be called
specifies an empty set of values.
It is used as the type returned by functions that
Besides the fundamental arithmetic types, there is a
conceptually infinite class of derived types constructed
from the fundamental types in the following ways:
which return objects of a given type
to objects of a given type
containing a sequence of objects of various types
capable of containing any one of several objects of various types.
of constructing objects can
is a manipulatable region of storage.
is an expression referring to an object.
An obvious example of an lvalue
expression is an identifier.
There are operators which yield lvalues:
is an expression of pointer type, then
expression referring to the object to which
The name ``lvalue'' comes from the assignment expression
in which the left operand
The discussion of each operator
below indicates whether it expects lvalue operands and whether it
A number of operators may, depending on their operands,
cause conversion of the value of an operand from one type to another.
This part explains the result to be expected from such
The conversions demanded by most ordinary operators are summarized under
``Arithmetic Conversions.''
The summary will be supplemented
as required by the discussion
A character or a short integer may be used wherever an
the value is converted to an integer.
Conversion of a shorter integer
to a longer preserves sign.
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 here,
variables range in value from
forces the values to range from 0 to 255.
On machines that treat characters as signed,
set are all non-negative.
However, a character constant specified
with an octal escape suffers sign extension
When a longer integer is converted to a shorter
it is truncated on the left.
Excess bits are simply discarded.
All floating arithmetic in C is carried out in double precision.
appears in an expression it is lengthened to
by zero padding its fraction.
for example by an assignment,
This result is undefined if it cannot be represented as a float.
On the VAX, the compiler can be directed to use single percision for expressions
containing only float and interger operands.
Conversions of floating values to integral type
are rather machine dependent.
In particular, the direction of truncation of negative numbers
The result is undefined if
it will not fit in the space provided.
Conversions of integral values to floating type
Some loss of accuracy occurs
if the destination lacks sufficient bits.
An expression of integral type 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.
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
Whenever an unsigned integer and a plain integer
are combined, the plain integer is converted to unsigned
and the result is unsigned.
is the least unsigned integer congruent to the signed
integer (modulo 2\v'-0.3'\s-2wordsize\s+2\v'0.3').
In a 2's complement representation,
this conversion is conceptual; and there is no actual change in the
When an unsigned \fBshort\fR integer is converted to
the value of the result is the same numerically as that of the
Thus the conversion amounts to padding with zeros on the left.
A great many operators cause conversions
and yield result types in a similar way.
This pattern will be called the ``usual arithmetic conversions.''
First, any operands of type
and any operands of type \fBunsigned char\fR
or \fBunsigned short\fR are converted
Then, if either operand is
the other is converted to
and that is the type of the result.
Otherwise, if either operand is \fBunsigned long\fR,
the other is converted to \fBunsigned long\fR and that
is the type of the result.
Otherwise, if either operand is
the other is converted to
and that is the type of the result.
Otherwise, if one operand is \fBlong\fR, and
the other is \fBunsigned int\fR, they are both
converted to \fBunsigned long\fR and that is
Otherwise, if either operand is
the other is converted to
and that is the type of the result.
Otherwise, both operands must be
and that is the type of the result.
The (nonexistent) value of a
object may not be used in any way,
and neither explicit nor implicit conversion may be applied.
Because a void expression denotes a nonexistent value,
such an expression may be used only
as an expression statement
(see ``Expression Statement'' under ``STATEMENTS'')
of a comma expression (see ``Comma Operator'' under ``EXPRESSIONS'').
An expression may be converted to
For example, this makes explicit the discarding of the value
of a function call used as an expression statement.
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
(see ``Additive Operators'')
are those expressions defined under ``Primary Expressions'',
``Unary Operators'', and ``Multiplicative Operators''.
Within each subpart, the operators have the same
Left- or right-associativity is specified
in each subsection for the operators
The precedence and associativity of all the expression
operators are summarized in the
grammar of ``SYNTAX SUMMARY''.
Otherwise, the order of evaluation of expressions
is undefined. In particular, the compiler
compute subexpressions in the order it believes
even if the subexpressions
The order in which subexpression evaluation takes place is unspecified.
Expressions involving a commutative and associative
may be rearranged arbitrarily even in the presence
to force a particular order of evaluation,
an explicit temporary must be used.
The handling of overflow and divide check
Most existing implementations of C ignore integer overflows;
division by 0 and all floating-point exceptions
varies between machines and is usually
adjustable by a library function.
subscripting, and function calls
primary-expression [ expression ]
primary-expression ( expression-list\v'0.5'\s-2opt\s0\v'-0.5' )
primary-expression . identifier
primary-expression \(mi> identifier\fR
expression-list , expression\fR
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 .\|.\|.'',
then the value of the identifier expression
to the first object in the array; and the
type of the expression is
Moreover, an array identifier is not an lvalue
Likewise, an identifier which is declared
``function returning .\|.\|.'',
when used except in the function-name position
of a call, is converted to ``pointer to function returning .\|.\|.''.
constant is a primary expression.
Character constants have type
and floating constants have type
A string is a primary expression.
Its type is originally ``array of
the same rule given above for identifiers,
this is modified to ``pointer to
result is a pointer to the first character
(There is an exception in certain initializers;
see ``Initialization'' under ``DECLARATIONS.'')
A parenthesized expression is a primary 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
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
and the type of the result is ``\|.\|.\|.\|''.
identical (by definition) to
this notation are contained in this subpart together
in ``Unary Operators'' and ``Additive Operators'' on identifiers,
The implications are summarized under ``Arrays, Pointers, and Subscripting''
under ``TYPES REVISITED.''
A function call is a primary expression followed by parentheses
empty, comma-separated list of expressions
which constitute the actual arguments to the
The primary expression must be of type ``function returning .\|.\|.,''
and the result of the function call is of type ``\|.\|.\|.\|''.
below, a hitherto unseen identifier followed
immediately by a left parenthesis
to represent a function returning
thus in the most common case, integer-valued functions
Any actual arguments of type
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
If conversion is needed, use a cast;
see ``Unary Operators'' and ``Type Names'' under
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.
change the values of its formal parameters, but
these changes cannot affect the values
of the actual parameters.
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.
A primary expression followed by a dot followed by an identifier
The first expression must be a structure or a union, and the identifier
must name a member of the structure or union.
The value is the named member of the structure or union, and it is
an lvalue if the first expression is an lvalue.
A primary expression followed by an arrow (built from
followed by an identifier
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.
Structures and unions are discussed in
``Structure, Union, and Enumeration Declarations'' under
Expressions with unary operators
( type-name ) expression\fR
sizeof\fI ( type-name )\fR
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 ``\|.\|.\|.\|''.
to the object referred to by the
If the type of the lvalue is ``\|.\|.\|.\|'',
the type of the result is ``pointer to .\|.\|.''.
is the negative of its operand.
The usual arithmetic conversions are performed.
The negative of an unsigned quantity is computed by
subtracting its value from
2\v'-0.5'\fIn\fR\^\v'0.5' where \fIn\fR\^ is the number of bits in
the corresponding signed type.
The result of the logical negation operator
is one if the value of its operand is zero, zero if the value of its
The type of the result is
It is applicable to any arithmetic type
operator yields the one's complement of its operand.
The usual arithmetic conversions are performed.
The type of the operand must be integral.
The object referred to by the lvalue operand of prefix
The value is the new value of the operand
See the discussions ``Additive Operators'' and ``Assignment
Operators'' for information on conversions.
The lvalue operand of prefix
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
The type of the result is the same as the type of the lvalue expression.
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
The type of the result is the same as the type of the lvalue
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
Type names are described in ``Type Names'' under ``Declarations.''
is undefined by the language
except in terms of the value of
However, in all existing implementations,
a byte is the space required to hold a
When applied to an array, the result is the total
number of bytes in the array.
The size is determined from
the objects in the expression.
This expression is semantically an
be used anywhere a constant is required.
Its major use is in communication with routines
like storage allocators and I/O systems.
may also be applied to a parenthesized type name.
In that case it yields the size in bytes of an object
\fBsizeof(\fItype\|\fR\^)\fR\^
\fBsizeof(\fItype\|\fB)-2\fR
\fB(sizeof(\fItype\|\fB))-2\fR.
The multiplicative operators
The usual arithmetic conversions are performed.
\fImultiplicative expression:
expression \(** expression
expression % expression\fR
operator indicates multiplication.
and expressions with several multiplications at the same
level may be rearranged by the compiler.
operator indicates division.
operator yields the remainder
from the division of the first expression by the second.
The operands must be integral.
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.
The usual arithmetic conversions are performed.
There are some additional type possibilities for each operator.
expression \(pl expression
expression \(mi expression\fR
operator is the sum of the operands.
A pointer to an object in an array and
a value of any integral type
The latter is in all cases converted to
by the length of the object to which the
of the same type as the original pointer
which points to another object in the same array,
appropriately offset from the original object.
to an object in an array, the expression
to the next object in the array.
No further type combinations are allowed for pointers.
and expressions with several additions at the same level may
be rearranged by the compiler.
operator is the difference of the operands.
The usual arithmetic conversions are performed.
a value of any integral type
may be subtracted from a pointer,
and then the same conversions for addition apply.
If two pointers to objects of the same type are subtracted,
(by division by the length of the object)
representing the number of
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.
Both perform the usual arithmetic conversions on their operands,
each of which must be integral.
Then the right operand is converted to
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.
On the VAX a negative right operand is interpreted as reversing
the direction of the shift.
expression >> expression\fR
Vacated bits are 0 filled.
The right shift is guaranteed to be logical
The relational operators group left to right.
\fIrelational-expression:
expression >= expression\fR
(greater than or equal to)
all yield 0 if the specified relation is false
The type of the result is
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
expression != expression\fR
are exactly analogous to the relational
operators except for their lower
have the same truth value).
A pointer may be compared to an integer
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.
Bitwise \s-1AND\s0 Operator
expression & expression\fR
and expressions involving
The usual arithmetic conversions are performed.
The result is the bitwise
function of the operands.
The operator applies only to integral
Bitwise Exclusive \s-1OR\s0 Operator
\fIexclusive-or-expression:
expression ^ expression\fR
and expressions involving
The usual arithmetic conversions are performed;
The operator applies only to integral
Bitwise Inclusive \s-1OR\s0 Operator
\fIinclusive-or-expression:
expression | expression\fR
and expressions involving
The usual arithmetic conversions are performed;
the result is the bitwise inclusive
function of its operands.
The operator applies only to integral
Logical \s-1AND\s0 Operator
\fIlogical-and-expression:
expression && expression\fR
operator groups left to right.
It returns 1 if both its operands
evaluate to nonzero, 0 otherwise.
evaluation; moreover, the second operand is not evaluated
if the first operand is 0.
The operands need not have the same type, but each
must have one of the fundamental
Logical \s-1OR\s0 Operator
\fIlogical-or-expression:
expression || expression\fR
operator groups left to right.
It returns 1 if either of its operands
evaluates to nonzero, 0 otherwise.
guarantees left to right evaluation; moreover,
the second operand is not evaluated
if the value of the first operand is nonzero.
The operands need not have the same type, but each
have one of the fundamental types
\fIconditional-expression:
expression ? expression : expression\fR
Conditional expressions group right to left.
The first expression is evaluated;
and if it is nonzero, 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.
If both are structures or unions of the same type,
the result has the type of the structure or union.
If both pointers are 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.
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
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
\fIassignment-expression:
In the simple assignment with
the value of the expression replaces that of the object
If both operands have arithmetic type,
the right operand is converted to the type of the left
preparatory to the assignment.
Second, both operands may be structures or unions of the same type.
Finally, if the left operand is a pointer, the right operand must in general be a pointer
However, the constant 0 may be assigned to a pointer;
it is guaranteed that this value will produce a null
pointer distinguishable from a pointer to any object.
The behavior of an expression
\fBE1\fR\^ \fIop\fR\^ = \fBE2\fR\^
taking it as equivalent to
\fBE1 = E1 \fIop\fR\^ (\fBE2\fR\^);
the left operand may be a pointer; in which case, the (integral) right
operand is converted as explained
in ``Additive Operators.''
All right operands and all nonpointer left operands must
expression , expression\fR
A pair of expressions separated by a comma is evaluated
left to right, and the value of the left expression is
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,
e.g., in lists of actual arguments
to functions (see ``Primary Expressions'') and lists
of initializers (see ``Initialization'' under ``DECLARATIONS''),
the comma operator as described in this subpart
can only appear in parentheses. For example,
\fBf(a, (t=3, t\(pl2), c)\fR
has three arguments, the second of which has the value 5.
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
decl-specifiers declarator-list\v'0.5'\s-2opt\s0\v'-0.5' ;\fR
The declarators in the declarator-list
contain the identifiers being declared.
consist of a sequence of type and storage class specifiers.
type-specifier decl-specifiers\v'0.5'\s-2opt\s0\v'-0.5'
sc-specifier decl-specifiers\v'0.5'\s-2opt\s0\v'-0.5'\fR
The list must be self-consistent in a way described below.
specifier does not reserve storage
and is called a ``storage class specifier'' only for syntactic convenience.
See ``Typedef'' for more information.
The meanings of the various storage classes were discussed in ``Names.''
declarations also serve as definitions
in that they cause an appropriate amount of storage to be reserved.
there must be an external definition (see ``External Definitions'')
for the given identifiers
somewhere outside the function in which they are declared.
declaration is best thought of as an
declaration, together with a hint to the compiler
that the variables declared will be heavily used.
such declarations in each function are effective.
Moreover, only variables of certain types will be stored in registers;
One other restriction applies to register variables:
cannot be applied to them.
Smaller, faster programs can be expected if register declarations
but future improvements in code generation
may render them unnecessary.
At most, one sc-specifier may be given in a declaration.
If the sc-specifier is missing from a declaration, it
struct-or-union-specifier
basic-type basic-type-specifiers
At most one of the words \fBlong\fR or \fBshort\fR
may be specified in conjunction with \fBint\fR;
the meaning is the same as if \fBint\fR were not mentioned.
The word \fBlong\fR may be specified in conjunction with
the meaning is the same as \fBdouble\fR.
The word \fBunsigned\fR may be specified alone, or
in conjunction with \fBint\fR or any of its short
or long varieties, or with \fBchar\fR.
Otherwise, at most on type-specifier may be
In particular, adjectival use of \fBlong\fR,
\fBshort\fR, or \fBunsigned\fR is not permitted
with \fBtypedef\fR names.
If the type-specifier is missing from a declaration,
it is taken to be \fBint\fR.
Specifiers for structures, unions, and enumerations are discussed in
``Structure, Union, and Enumeration Declarations.''
names are discussed in ``Typedef.''
The declarator-list appearing in a declaration
is a comma-separated sequence of declarators,
each of which may have an initializer.
init-declarator , declarator-list
declarator initializer\v'0.5'\s-2opt\s0\v'-0.5'\fR
Initializers are discussed in ``Initialization''.
The specifiers in the declaration
indicate the type and storage class of the objects to which the
Declarators have the syntax:
declarator [ constant-expression\v'0.5'\s-2opt\s0\v'-0.5' ]\fR
the same as in expressions.
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
Each declarator contains exactly one identifier; it is this identifier that
If an unadorned identifier appears
as a declarator, then it has the type
indicated by the specifier heading the declaration.
A declarator in parentheses is identical to the unadorned declarator,
but the binding of complex declarators may be altered by parentheses.
Now imagine a declaration
is a type-specifier (like
Suppose this declaration makes the identifier have type
where the ``\|.\|.\|.\|'' is empty if
is just a plain identifier
the type of the contained identifier is
then the contained identifier has the type
``\|.\|.\|. function returning
\fBD\|[\|\fIconstant-expression\fB\|]\fR
then the contained identifier has type
In the first case, the constant
whose value is determinable at compile time
and whose value is positive.
(Constant expressions are defined precisely in ``Constant Expressions.'')
When several ``array of'' specifications are adjacent, a multidimensional
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,
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
of initial elements supplied.
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 multidimensional array).
Not all the possibilities
allowed by the syntax above are actually
The restrictions are as follows:
although they may return pointers;
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.
As an example, the declaration
\fBint i, \(**ip, f(), \(**fip(), (\(**pfi)();\fR
returning a pointer to an integer,
It is especially useful to compare the last two.
The declaration suggests,
and the same construction in an expression
requires, the calling of a function
Using indirection through the (pointer) result
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;
\fBfloat fa[17], \(**afp[17];\fR
\fBstatic int x3d[3][5][7];\fR
declares a static 3-dimensional array of integers,
is an array of three items;
each item is an array of five arrays;
each of the latter arrays is an array of seven
may reasonably appear in an expression.
The first three have type ``array''
Structure and Union Declarations
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
Structure and union specifiers have the same form.
\fIstruct-or-union-specifier:
struct-or-union { struct-decl-list }
struct-or-union identifier { struct-decl-list }
struct-or-union identifier
is a sequence of declarations for the members of the structure or union:
struct-declaration struct-decl-list
type-specifier struct-declarator-list ;
\fIstruct-declarator-list:
struct-declarator , struct-declarator-list\fR
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
a non-negative constant expression,
is set off from the field name by a colon.
declarator : constant-expression
Within a structure, the objects declared
have addresses which increase as the declarations
Each nonfield member of a structure
begins on an addressing boundary appropriate
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
left to right on the 3B 20.
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, a field with a width of 0
specifies alignment of the next field at an implementation dependant boundary.
The language does not restrict the types of things that
but implementations are not required to support any but
fields may be considered to be unsigned.
fields are not signed and have only integer values;
are treated as containing a sign.
it is strongly recommended that fields be declared as
there are no arrays of fields,
and the address-of operator
may not be applied to them, so that there are no pointers to
A union may be thought of as a structure all of whose members
begin at offset 0 and whose size is sufficient to contain
At most, one of the members can be stored in a union
A structure or union specifier of the second form, that is, one of
\fBstruct \fIidentifier { struct-decl-list \fR}
\fBunion \fIidentifier { struct-decl-list \fR}
declares the identifier to be the
of the structure specified by the list.
A subsequent declaration may then use
the third form of specifier, one of
\fBstruct \fIidentifier\fR
\fBunion \fIidentifier\fR
Structure tags allow definition of self-referential
structures. Structure tags 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.
The third form of a structure or union specifier may be
used prior to a declaration which gives the complete specification
of the structure or union in situations in which the size
of the structure or union is unnecessary.
The size is unnecessary in two situations: when a
pointer to a structure or union is being declared and
when a \fBtypedef\fR name is declared to be a synonym
for a structure or union.
This, for example, allows the declaration of a pair
of structures which contain pointers to each other.
The names of members and tags do not conflict
with each other or with ordinary variables.
A particular name may not be used twice
but the same name may be used in several different structures in the same scope.
A simple but important example of a structure declaration is
the following binary tree structure:
which contains an array of 20 characters, an integer, and two pointers
Once this declaration has been given, the
\fBstruct tnode s, \(**sp;\fR
to be a structure of the given sort
to be a pointer to a structure
With these declarations, the expression
field of the structure to which
refers to the left subtree pointer
refers to the first character of the
member of the right subtree of
Enumeration variables and constants have integral type.
enum\fI { enum-list \fR}\fB
enum \fIidentifier { enum-list \fR}\fB
identifier = constant-expression\fR
The identifiers in an enum-list are declared as constants
and may appear wherever constants are required.
appear, then the values of the
corresponding constants begin at 0 and increase by 1 as the declaration is
gives the associated identifier the value
indicated; subsequent identifiers continue the progression from the assigned value.
The names of enumerators in the same scope must all be distinct
from each other and from those of ordinary variables.
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.
\fBenum color { chartreuse, burgundy, claret=20, winedark };
enum color \(\(**\(**cp, col;
if (\(\(**\(**cp == burgundy) ...\fR
the enumeration-tag of a type describing various colors,
as a pointer to an object of that type,
as an object of that type.
The possible values are drawn from the set {0,1,20,21}.
A declarator may specify an initial value for the
identifier being declared.
The initializer is preceded by
consists of an expression or a list of values nested in braces.
initializer-list , initializer-list\fR
{ \fIinitializer-list \fR}
{ \fIinitializer-list\fR , }
All the expressions in an initializer
for a static or external variable must be constant
expressions, which are described in ``CONSTANT EXPRESSIONS'',
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
expressions involving constants and previously declared variables and functions.
Static and external variables that are not initialized are
guaranteed to start off as zero.
Automatic and register variables that are not initialized
are guaranteed to start off as garbage.
When an initializer applies to a
(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.
When the declared variable is an
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 zeros.
It is not permitted to initialize unions or automatic aggregates.
Braces may in some cases be omitted.
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.
A final abbreviation allows a
array to be initialized by a string.
In this case successive characters of the string
initialize the members of the array.
\fBint x[] = { 1, 3, 5 };\fR
as a one-dimensional array which has three members, since no size was specified
and there are three initializers.
is a completely-bracketed initialization:
1, 3, and 5 initialize the first row of
Likewise, the next two lines initialize
The initializer ends early and therefore
Precisely, the same effect could have been achieved by
1, 3, 5, 2, 4, 6, 3, 5, 7
begins with a left brace but that for
therefore, three elements from the list are used.
Likewise, the next three are taken successively for
{ 1 }, { 2 }, { 3 }, { 4 }
initializes the first column of
(regarded as a two-dimensional array)
\fBchar msg[] = "Syntax error on line %s\en";\fR
shows a character array whose members are initialized
In two contexts (to specify type conversions explicitly
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
type-specifier abstract-declarator
abstract-declarator\fR\^ [ \fIconstant-expression\v'0.5'\s-2opt\s0\v'-0.5' \fR\^]
\fI( abstract-declarator \fR)
is required to be nonempty.
it is possible to identify uniquely the location in the abstract-declarator
where the identifier would appear if the construction were a declarator
The named type is then the same as the type of the
name respectively the types ``integer,'' ``pointer to integer,''
``array of three pointers to integers,''
``pointer to an array of three integers,''
``function returning pointer to integer,''
``pointer to function returning an integer,''
and ``array of three pointers to functions returning an integer.''
Declarations whose ``storage class'' is
do not define storage but instead
define identifiers which can be used later
as if they were type keywords naming fundamental
Within the scope of a declaration involving
each identifier appearing as part of
any declarator therein becomes syntactically
equivalent to the type keyword
associated with the identifier
in the way described in ``Meaning of Declarators.''
\fBtypedef int MILES, \(**KLICKSP;
typedef struct { double re, im; } complex;\fR
are all legal declarations; the type of
is ``pointer to \fBint\fR, ''
is the specified structure.
is a pointer to such a structure.
does not introduce brand-new types, only synonyms for
types which could be specified in another way.
is considered to have exactly the same type as
Except as indicated, statements are executed in sequence.
Most statements are expression statements, which have
Usually expression statements are assignments or function
Compound Statement or Block
So that several statements can be used where one is expected,
the compound statement (also, and equivalently, called ``block'') is provided:
{ declaration-list\v'0.5'\s-2opt\s0\v'-0.5' statement-list\v'0.5'\s-2opt\s0\v'-0.5' }
declaration declaration-list
statement statement-list\fR
If any of the identifiers
in the declaration-list were previously declared,
the outer declaration is pushed down for the duration of the block,
after which it resumes its force.
variables are performed each time the block is entered at the top.
to transfer into a block;
in that case the initializations are not performed.
variables are performed only once when the program
declarations do not reserve storage
so initialization is not permitted.
The two forms of the conditional statement are
\fBif\fR\^ ( \fIexpression\fR\^ ) \fIstatement\fR\^
\fBif\fR\^ ( \fIexpression\fR\^ ) \fIstatement \fBelse \fIstatement\fR\^
In both cases, the expression is evaluated;
and if it is nonzero, the first substatement
In the second case, the second substatement is executed
The ``else'' ambiguity is resolved by connecting
with the last encountered
\fBwhile\fR\^ ( \fIexpression\fR\^ ) \fIstatement\fR\^
The substatement is executed repeatedly
so long as the value of the
expression remains nonzero.
The test takes place before each execution of the
\fBdo \fIstatement \fBwhile\fR\^ ( \fIexpression \fR\^) ;
The substatement is executed repeatedly until
the value of the expression becomes 0.
The test takes place after each execution of the
\fBfor\fI ( exp-1\v'0.5'\s-2opt\s0\v'-0.5' ; exp-2\v'0.5'\s-2opt\s0\v'-0.5' ; exp-3\v'0.5'\s-2opt\s0\v'-0.5' ) statement\fR
Except for the behavior of \fBcontinue\fR,
this statement is equivalent to
\fBwhile\fR\^ ( \fIexp-2\ ) \fR\^
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
The third expression often specifies an incrementing
that is performed after each iteration.
Any or all of the expressions may be dropped.
other missing expressions are simply
dropped from the expansion above.
statement causes control to be transferred
to one of several statements depending on
the value of an expression.
\fBswitch\fR\^ ( \fIexpression\fR\^ ) \fIstatement\fR\^
The usual arithmetic conversion is performed on the
expression, but the result must be
The statement is typically compound.
Any statement within the statement
may be labeled with one or more case prefixes
\fBcase \fIconstant-expression \fR:
No two of the case constants in the same switch
Constant expressions are precisely defined in ``CONSTANT EXPRESSIONS.''
There may also be at most one statement prefix of the
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
If no case matches and if there is no
none of the statements in the
do not alter the flow of control,
which continues unimpeded across such prefixes.
To exit from a switch, see
Usually, the statement that is the subject of a switch is compound.
Declarations may appear at the head of this
initializations of automatic or register variables
causes termination of the smallest enclosing
statement following the terminated statement.
causes control to pass to the loop-continuation portion of the
statement; that is to the end of the loop.
More precisely, in each of the statements
\fBwhile (\|.\|.\|.\|) { do { for (\|.\|.\|.\|) {\fR
\fIstatement ; statement ; statement ;\fR
\fBcontin: ; contin: ; contin: ;
is a null statement, see ``Null Statement''.)
A function returns to its caller by means of
statement which has one of the
return \fIexpression \fR;
In the first case, the returned value is undefined.
In the second case, the value of the expression
is returned to the caller
If required, the expression is converted,
as if by assignment, to the type of
function in which it appears.
Flowing off the end of a function is
equivalent to a return with no returned value.
The expression may be parenthesized.
Control may be transferred unconditionally by means of
\fBgoto \fIidentifier \fR;
The identifier must be a label
(see ``Labeled Statement'')
located in the current function.
Any statement may be preceded by
label prefixes of the form
which serve to declare the identifier
The only use of a label is as a target of a
The scope of a label is the current function,
excluding any subblocks in which the same identifier has been redeclared.
The null statement has the form
A null statement is useful to carry a label just before the
of a compound statement or to supply a null
body to a looping statement such as
A C program consists of a sequence of external definitions.
An external definition declares an identifier to
The type-specifier (see ``Type Specifiers'' in
``DECLARATIONS'') may also be empty, in which
case the type is taken to be
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.
External Function Definitions
Function definitions have the form
decl-specifiers\v'0.5'\s-2opt\s0\v'-0.5' function-declarator function-body\fR
among the decl-specifiers
see ``Scope of Externals'' in
``SCOPE RULES'' 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
the function being defined.
declarator ( parameter-list\v'0.5'\s-2opt\s0\v'-0.5' )
identifier , parameter-list\fR
declaration-list\v'0.5'\s-2opt\s0\v'-0.5' compound-statement\fR
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
The only storage class which may be specified is
if it is specified, the corresponding actual parameter
will be copied, if possible, into a register
at the outset of the function.
A simple example of a complete function definition is
is the function-declarator;
is the declaration-list for
block giving the code for the statement.
The C program converts all
so formal parameters declared
have their declaration adjusted to read
All \fBchar\fR and \fBshort\fR formal parameter
declarations are similarly adjusted
Also, since a reference to an array in any context
(in particular as an actual parameter)
a pointer to the first element of the array,
declarations of formal parameters declared ``array of .\|.\|.\|''
are adjusted to read ``pointer to .\|.\|.\|.''
External Data Definitions
An external data definition has the form
The storage class of such data may be
be compiled at the same time. The source text of the
may be kept in several files, and precompiled
routines may be loaded from
Communication among the functions of a program
may be carried out both through explicit calls
and through manipulation of external data.
Therefore, there are two kinds of scopes to consider:
first, what may be called the
of an identifier, which is essentially the
region of a program during which it may
be used without drawing ``undefined identifier''
associated with external identifiers,
which is characterized by the rule
that references to the same external
identifier are references to the same object.
The lexical scope of identifiers declared in external definitions
persists from the definition through
the end of the source file
The lexical scope of identifiers which are formal parameters
persists through the function with which they are
The lexical scope of identifiers declared at the head of a block
persists until the end of the block.
The lexical scope of labels is the whole of the
function in which they appear.
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.
Remember also (see ``Structure, Union, and Enumeration Declarations'' in
``DECLARATIONS'') that tags, identifiers associated with
and identities associated with structure and union members
form three disjoint classes
Members and tags follow the same scope rules
The \fBenum\fR constants are in the same
class as ordinary variables and follow the same scope rules.
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:
\fBtypedef float distance;
must be present in the second declaration,
or it would be taken to be
a declaration with no declarators and type
If a function refers to an identifier declared to be
then somewhere among the files or libraries
constituting the complete program
there must be at least one external definition
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.
It is illegal to explicitly initialize any external
identifier more than once in the set of files and libraries
comprising a multi-file program.
It is legal to have more than one data definition
for any external non-function identifier;
explicit use of \fBextern\fR does not
change the meaning of an external declaration.
In restricted environments, the use of the \fBextern\fR
storage class takes on an additional meaning.
In these environments, the explicit appearance of the
\fBextern\fR keyword in external data declarations of
identities without initialization indicates that
the storage for the identifiers is allocated elsewhere,
either in this file or another file.
It is required that there be exactly one definition of
each external identifier (without \fBextern\fR)
in the set of files and libraries
comprising a mult-file program.
at the top level in external definitions
are not visible in other files.
Functions may be declared
The C compiler contains a preprocessor capable
of macro substitution, conditional compilation,
and inclusion of named files.
There may be any number of blanks and horizontal tabs
between the \fB#\fR and the directive.
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.
A compiler-control line of the form
\fB#define \fIidentifier token-string\v'0.5'\s-2opt\s0\v'-0.5'\fR
causes the preprocessor to replace subsequent instances
of the identifier with the given string of tokens.
Semicolons in or at the end of the token-string are part of that string.
\fB#define \fIidentifier(identifier, ... )token-string\v'0.5'\s-2opt\s0\v'-0.5'\fR
where there is no space between the first identifier
is a macro definition with arguments.
There may be zero or more formal parameters.
Subsequent instances of the first identifier followed
a sequence of tokens delimited by commas, and a
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.
Strings and character constants in the token-string are scanned
for formal parameters, but
strings and character constants in the rest of the program are
not scanned for defined identifiers
In both forms the replacement string is rescanned for more
a long definition may be continued on another line
at the end of the line to be continued.
This facility is most valuable for definition of ``manifest constants,''
int table\|[\|TABSIZE\|]\|;\fR
A control line of the form
\fB#undef \fIidentifier\fR
identifier's preprocessor definition (if any) to be forgotten.
If a \fB#define\fRd identifier is the subject of a subsequent
\fB#define\fR with no intervening \fB#undef\fR, then
the two token-strings are compared textually.
If the two token-strings are not identical
(all white space is considered as equivalent), then
the identifier is considered to be redefined.
A compiler control line of
\fB#include\fI "filename\|\fR"
causes the replacement of that
line by the entire contents of the file
The named file is searched for first in the directory
of the file containing the \fB#include\fR,
and then in a sequence of specified or standard places.
Alternatively, a control line of the form
\fB#include\fI <filename\|\fR>
searches only the specified or standard places
and not the directory of the \fB#include\fR.
(How the places are specified is not part of the language.)
A compiler control line of the form
\fB#if \fIrestricted-constant-expression\fR
checks whether the restricted-constant expression evaluates to nonzero.
(Constant expressions are discussed in ``CONSTANT EXPRESSIONS'';
the following additional restrictions apply here:
the constant expression may not contain
casts, or an enumeration constant.)
A restricted constant expression may also contain the
additional unary expression
\fBdefined \fIidentifier\fR
\fBdefined( \fIidentifier )\fR
which evaluates to one if the identifier is currently
defined in the preprocessor and zero if it is not.
All currently defined identifiers in restricted-constant-expressions
are replaced by their token-strings (except those identifiers
modified by \fBdefined\fR) just as in normal text.
The restricted constant expression will be evaluated only
after all expressions have finished.
During this evaluation, all undefined (to the procedure)
identifiers evaluate to zero.
A control line of the form
\fB#ifdef \fIidentifier\fR
checks whether the identifier is currently defined
in the preprocessor; i.e., whether it has been the
It is equivalent to \fB#ifdef(\fIidentifier\fB)\fR.
A control line of the form
\fB#ifndef \fIidentifier\fR
checks whether the identifier is currently undefined
\fB#if !\|defined(\fIidentifier\fB)\fR.
All three forms are followed by an arbitrary number of lines,
possibly containing a control line
and then by a control line
If the checked condition is true,
If the checked condition is false, then any lines between
These constructions may be nested.
For the benefit of other preprocessors which generate C programs,
\fB#line \fIconstant "filename\fR"
causes the compiler to believe, for purposes of error
that the line number of the next source line is given by the constant and the current input
file is named by "\fIfilename\fR".
If "\fIfilename\fR" is absent, the remembered file name does not change.
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
In a declaration inside a function,
if a storage class but no type
is given, the identifier is assumed
if a type but no storage class is indicated,
the identifier is assumed to
An exception to the latter rule is made for
If the type of an identifier is ``function returning .\|.\|.\|,''
it is implicitly declared to be
In an expression, an identifier
declared to be ``function returning
This part summarizes the operations
which can be performed on objects of certain types.
Structures and unions may be assigned, passed as arguments to functions,
and returned by functions.
Other plausible operators, such as equality comparison
to a structure or union member, the
of the \fB->\fR or the \fB.\fR
must specify a member of the aggregate
named or pointed to by the expression
In general, a member of a union may not be inspected
unless the value of the union has been assigned using that same member.
However, one special guarantee is made by the language in order
to simplify the use of unions:
if a union contains several structures that share a common initial sequence
and if the union currently contains one of these structures,
it is permitted to inspect the common initial part of any of
the contained structures.
For example, the following is a legal fragment:
... sin(u.nf.floatnode) ...\fR
There are only two things that
can be done with a function \fBm\fR,
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.
Thus, to pass one function to another, one
explicitly in the calling routine since its appearance
Arrays, Pointers, and Subscripting
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
By definition, the subscript operator
Because of the conversion rules
appearance, subscripting is a commutative operation.
A consistent rule is followed in the case of
appearing in an expression is converted to
a pointer to an (n-1)-dimensional
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.
is a 3\(mu5 array of integers.
appears in an expression, it is converted
to a pointer to (the first of three) 5-membered arrays of integers.
is first converted to a pointer as described;
is converted to the type of
which involves multiplying
length the object to which the pointer points,
namely 5-integer objects.
The results are added and indirection applied to
yield an array (of five 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.
row-wise (last subscript varies fastest)
and the first subscript in the declaration helps determine
the amount of storage consumed by an array.
Arrays play no other part in subscript calculations.
Explicit Pointer Conversions
Certain conversions involving pointers are permitted
but have implementation-dependent aspects.
They are all specified by means of an explicit type-conversion
operator, see ``Unary Operators'' under``EXPRESSIONS'' and
``Type Names''under ``DECLARATIONS.''
A pointer may be converted to any of the integral types large
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
Details for some particular machines are given below.
An object of integral type may be explicitly converted to a pointer.
The mapping always carries an integer converted from a pointer back to the same pointer
but is otherwise machine dependent.
A pointer to one type may be converted to a pointer to another type.
The resulting pointer may cause addressing exceptions
the subject pointer does not refer to an object suitably aligned in storage.
a pointer to an object of a given size may be converted to a pointer to an object
and back again without change.
a storage-allocation routine
might accept a size (in bytes)
of an object to allocate, and return a
it might be used in this way.
\fBextern char \(**malloc();
dp = (double \(**) malloc(sizeof(double));
must ensure (in a machine-dependent way)
that its return value is suitable for conversion to a pointer to
of the function is portable.
corresponds to a 16-bit integer and
have no alignment requirements; everything else must have an even address.
pointers are 32 bits long and measure bytes.
Elementary objects are aligned on a boundary equal to their
quantities need be aligned only on even 4-byte boundaries.
Aggregates are aligned on the strictest boundary required by
any of their constituents.
The 3B 20 computer has 24-bit pointers placed into 32-bit quantities.
aligned on 4-byte boundaries. \fBShort\fRs are aligned in all cases on
2-byte boundaries. Arrays of characters, all structures,
\fBint\fR\^s, \fBlong\fR\^s, \fBfloat\fR\^s, and \fBdouble\fR\^s are aligned on 4-byte
boundries; but structure members may be packed tighter.
In several places C requires expressions that evaluate to
as array bounds, and in initializers.
In the first two cases, the expression can
involve only integer constants, character constants,
connected by the binary operators
\(pl \(mi \(** / % & | ^ << >> == != < > <= >= && ||
or by the unary operators
or by the ternary operator
Parentheses can be used for grouping
but not for function calls.
More latitude is permitted for initializers;
besides constant expressions as discussed above,
one can also use floating constants
operator to external or static objects
and to external or static arrays subscripted
with a constant expression.
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.
Portability Considerations
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.
Purely hardware issues like
word size and the properties of floating point arithmetic and integer division
have proven in practice to be not much of a problem.
Other facets of the hardware are reflected
in differing implementations.
particularly sign extension
(converting a negative character into a negative integer)
and the order in which bytes are placed in a word,
are nuisances that must be carefully watched.
Most of the others are only minor problems.
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;
declarations are ignored.
Some difficulties arise only when
dubious coding practices are used.
It is exceedingly unwise to write programs
on any of these properties.
The order of evaluation of function arguments
is not specified by the language.
The order in which side effects take place
Since character constants are really objects of type
multicharacter character constants may be permitted.
The specific implementation
is very machine dependent
because the order in which characters
varies from one machine to another.
Fields are assigned to words and characters to integers right to left
and left to right on other machines.
These differences are invisible to isolated programs
that do not indulge in type punning (e.g.,
pointer and inspecting the pointed-to storage)
but must be accounted for when conforming to externally-imposed
This summary of C syntax is intended more for aiding comprehension
than as an exact statement of the language.
The basic expressions are:
\fBsizeof (\fItype-name\fB)\fI
expression binop expression
expression ? expression : expression
primary ( expression-list\v'0.5'\s-2opt\s0\v'-0.5' )
The primary-expression operators
have highest priority and group left to right.
\(** & \(mi ! \s+2~\s0 \(pl\(pl \(mi\(mi \fBsizeof\fI ( type-name \fR)
have priority below the primary operators
but higher than any binary operator
group left to right; they have priority
The conditional operator groups right to left.
Assignment operators all have the same
priority and all group right to left.
= \(pl= \(mi= \(**= /= %= >>= <<= &= ^= |=
The comma operator has the lowest priority and groups left to right.
decl-specifiers init-declarator-list\v'0.5'\s-2opt\s0\v'-0.5' ;
type-specifier decl-specifiers\v'0.5'\s-2opt\s0\v'-0.5'
sc-specifier decl-specifiers\v'0.5'\s-2opt\s0\v'-0.5'
struct-or-union-specifier
basic-type basic-type-specifiers
enum \fIidentifier { enum-list }\fB
identifier = constant-expression
init-declarator , init-declarator-list
declarator initializer\v'0.5'\s-2opt\s0\v'-0.5'
declarator [ constant-expression\v'0.5'\s-2opt\s0\v'-0.5' ]
\fIstruct-or-union-specifier:\fB
struct\fI { struct-decl-list }\fB
struct \fIidentifier { struct-decl-list }\fB
union { \fIstruct-decl-list }\fB
union \fIidentifier { struct-decl-list }\fB
struct-declaration struct-decl-list
type-specifier struct-declarator-list ;
\fIstruct-declarator-list:
struct-declarator , struct-declarator-list
declarator : constant-expression
initializer-list , initializer-list
type-specifier abstract-declarator
abstract-declarator [ constant-expression\v'0.5'\s-2opt\s0\v'-0.5' ]
{ declaration-list\v'0.5'\s-2opt\s0\v'-0.5' statement-list\v'0.5'\s-2opt\s0\v'-0.5' }
declaration declaration-list
\fBif\fI ( expression ) statement
\fBif\fI ( expression ) statement \fBelse\fI statement
\fBwhile\fI ( expression ) statement
\fBdo\fI statement \fBwhile\fI ( expression ) ;
\fBfor\fI (exp\v'0.3'\s-2opt\s0\v'-0.3'\fB;\fIexp\v'0.3'\s-2opt\s0\v'-0.3'\fB;\fIexp\v'0.3'\s-2opt\s0\v'-0.3'\fI) statement
\fBswitch\fI ( expression ) statement
\fBcase\fI constant-expression : statement
\fBdefault\fI : statement
external-definition program
decl-specifier\v'0.5'\s-2opt\s0\v'-0.5' function-declarator function-body
declarator ( parameter-list\v'0.5'\s-2opt\s0\v'-0.5' )
identifier , parameter-list
declaration-list\v'0.5'\s-2opt\s0\v'-0.5' compound-statement
\fBextern\fI declaration\fB ;
\fBstatic\fI declaration\fB ;
\fB#define\fI identifier token-string\v'0.3'\s-2opt\s0\v'-0.3'\fB
\fB#define\fI identifier\fB(\fIidentifier\fB,...)\fItoken-string\v'0.5'\s-2opt\s0\v'-0.5'\fB
\fB#undef\fI identifier\fB
\fB#include "\fIfilename\|\fB"
#include <\fIfilename\|\fB>
\fB#if\fI restricted-constant-expression\fB
\fB#ifdef\fI identifier\fB
\fB#ifndef\fI identifier\fB
\fB#line\fI constant \fB"\fIfilename\|\fB"