Mini-Unix/usr/doc/c/c2

.ul
7.  Expressions
.et
The precedence of expression operators is the same
as the order of the major
subsections of this section (highest precedence first).
Thus the expressions referred to as the operands of \fG+\fR
(\(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
in each subsection for the operators
discussed therein.
The precedence and associativity of all the expression
operators is summarized in an
appendix.
.pg
Otherwise the order of evaluation of expressions
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.
.ms
7.1  Primary expressions
.et
Primary expressions
involving \fG.\fR^, \fG\(mi>\fR, subscripting, and function calls
group left to right.
.ms
7.1.1  \fIidentifier\fR
.et
An identifier is a primary expression, provided it has been
suitably declared as discussed below.
Its type is specified by its declaration.
However, if the type of the identifier is ``array of .^.^.'',
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.
.pg
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 .^.^.''.
.ms
7.1.2  \fIconstant\fR
.et
A decimal, octal, character, or floating
constant is a primary expression.
Its type is \fGint\fR in the first three cases,
\fGdouble\fR in the last.
.ms
7.1.3  \fIstring\fR
.et
A string is a primary expression.
Its type is originally ``array of \fGchar\fR''; but following
the same rule as in \(sc7.1.1 for identifiers,
this is modified to ``pointer to \fGchar\fR'' and the
result is a pointer to the first character
in the string.
.ms
7.1.4  \fG(\fI expression \fG)\fR
.et
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
lvalue.
.ms
7.1.5  \fIprimary-expression\fG [\fI expression \fG]\fR
.et
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 \fGint\fR,
and the type of the result is ``^.^.^.^''.
The expression ``E1[E2]'' is
identical (by definition) to ``\**^(^^(^E1^)^+^(^E2^)^^)^''.
All the clues
needed to understand
this notation are contained in this section together
with the discussions
in \(sc\(sc 7.1.1, 7.2.1, and 7.4.1 on identifiers,
\fG\**\fR, and \fG+\fR respectively;
\(sc14.3 below summarizes the implications.
.ms
7.1.6  \fIprimary-expression \fG( \fIexpression-list\*(op \fG)
.et
A function call is a primary expression followed by parentheses
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.
.pg
Any actual arguments of type \fGfloat\fR are
converted to \fGdouble\fR before the call;
any of type \fGchar\fR are converted to \fGint\fR.
.pg
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.
A function may
change the values of its formal parameters, but
these changes cannot possibly affect the values
of the actual parameters.
On the other hand, it is perfectly possible
to pass a pointer on the understanding
that the function may change the value
of the object to which the pointer points.
.pg
Recursive calls to any
function are permissible.
.ms
7.1.7  \fIprimary-lvalue \fG.\fI member-of-structure\fR
.et
An lvalue expression followed by a dot followed by the name
of a member of a structure is a primary expression.
The object referred to
by the lvalue is assumed to have the
same form as the structure
containing the structure member.
The result of the expression is an lvalue appropriately
offset from the origin of the given lvalue
whose type is that of the
named structure member.
The given lvalue is not required to have
any particular type.
.pg
Structures are discussed in \(sc8.5.
.ms
7.1.8  \fIprimary-expression \fG\(mi>\fI member-of-structure\fR
.et
The primary-expression is assumed to be a pointer
which points to an object of the same form
as the structure of which the member-of-structure is
a part.
The result is an lvalue appropriately
offset from the origin of the pointed-to structure
whose type is that of the named structure member.
The type of the primary-expression need not
in fact be pointer; it is sufficient that
it be a pointer, character, or integer.
.pg
Except for the relaxation of the requirement that
E1 be of pointer type, the expression ``E1\(mi>MOS''
is exactly equivalent to ``(\**E1).MOS''.
.ms
7.2  Unary operators
.et
Expressions with unary operators
group right-to-left.
.ms
7.2.1  \fG\**\fI expression\fR
.et
The unary \fG\**\fR operator
means
.ft I
indirection:
.ft R
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 ``^.^.^.^''.
.ms
7.2.2  \fG&\fI lvalue-expression\fR
.et
The result of the unary \fG&\fR operator is a pointer
to the object referred to by the
lvalue-expression.
If the type of the lvalue-expression is ``^.^.^.^'',
the type of the result is ``pointer to .^.^.''.
.ms
7.2.3  \fG\(mi\fI expression\fR
.et
The result is the negative of the expression,
and has the same type.
The type of the expression must be \fGchar\fR, \fGint\fR, \fGfloat\fR,
or \fGdouble\fR.
.ms
7.2.4  \fG!\fI expression\fR
.et
The result of the logical negation operator \fG!\fR
is 1 if the value of the expression is 0, 0 if the value of the
expression is non-zero.
The type of the result is \fGint\fR.
This operator is applicable only to \fGint\fRs or \fGchar\fRs.
.ms
7.2.5  \fG\*~\fI expression\fR
.et
The \*~ operator yields the one's complement of its operand.
The type of the expression must be \fGint\fR or \fGchar\fR,
and the result is \fGint\fR.
.ms
7.2.6  ++ \fIlvalue-expression\fR
.et
The object referred to by the lvalue expression
is incremented.
The value is the new value of the lvalue expression
and the type is the type of the lvalue.
If the expression is \fGint\fR or \fGchar\fR,
it is incremented by 1;
if it is a pointer to an object, it is incremented
by the length of the object.
++ is applicable only to these types.
(Not, for example, to \fGfloat\fR or \fGdouble\fR.)
.ms
7.2.7  \fR\(mi\(mi\fI lvalue-expression\fR
.et
The object referred to by the lvalue expression is decremented
analogously to the ++ operator.
.ms
7.2.8  \fIlvalue-expression ++
.et
The result is the value of the object
referred to by the lvalue expression.
After the result is noted, the object
referred to by the lvalue is incremented in the same
manner as for the prefix ++ operator: by 1 for an \fGint\fR
or \fGchar\fR, by the length of the pointed-to object for a pointer.
The type of the result is the same as the
type of the lvalue-expression.
.ms
7.2.9  \fIlvalue-expression \(mi\(mi
.et
The result of the expression is the value of the object
referred to by the
the lvalue expression.
After the result is noted, the object referred
to by the lvalue expression is decremented in a way
analogous to the postfix ++ operator.
.ms
7.2.10  \fGsizeof \fIexpression
.et
The \fGsizeof\fR operator yields the size,
in bytes, of its operand.
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.
.ms
7.3  Multiplicative operators
.et
The multiplicative operators
\fG\**\fR, \fG/\fR, and \fG%\fR
group left-to-right.
.ms
7.3.1  \fIexpression\fG \** \fIexpression\fR
.et
The binary \fG\**\fR operator indicates multiplication.
If both operands are \fGint\fR or \fGchar\fR, the result
is \fGint\fR; if one is \fGint\fR or \fGchar\fR and one \fGfloat\fR or \fGdouble\fR, the
former is converted to \fGdouble\fR, and the result is \fGdouble\fR;
if both are \fGfloat\fR or \fGdouble\fR, the result is \fGdouble\fR.
No other combinations are allowed.
.ms
7.3.2  \fIexpression \fG/\fI expression\fR
.et
The binary \fG/\fR operator indicates division.
The same type considerations as for multiplication
apply.
.ms
7.3.3  \fIexpression \fG%\fI expression\fR
.et
The binary \fG%\fR operator yields the remainder
from the division of the first expression by the second.
Both operands must be \fGint\fR or \fGchar\fR, and the
result is \fGint\fR.
In the current implementation,
the remainder has the same sign as the dividend.
.ms
7.4  Additive operators
.et
The additive operators \fG+\fR and \fG\(mi\fR group left-to-right.
.ms
7.4.1  \fIexpression \fG+\fI expression\fR
.et
The result is the sum of the expressions.
If both operands are \fGint\fR or \fGchar\fR,
the result is \fGint\fR.
If both
are \fGfloat\fR or \fGdouble\fR, the result is \fGdouble\fR.
If one is \fGchar\fR or \fGint\fR and one is \fGfloat\fR
or \fGdouble\fR, the former is converted to \fGdouble\fR and the result is \fGdouble\fR.
If an \fGint\fR or \fGchar\fR is added to a pointer, the former
is converted by multiplying it
by the length of the object to which the
pointer points and the result is a pointer
of the same type as the original pointer.
Thus if P is a pointer
to an object, the expression ``P+1'' is a pointer
to another object of the same type as
the first and immediately following
it in storage.
.pg
No other type combinations are allowed.
.ms
7.4.2  \fIexpression \fG\(mi \fIexpression\fR
.et
The result is the difference of the operands.
If both operands are \fGint\fR, \fGchar\fR, \fGfloat\fR, or \fGdouble\fR,
the same type considerations
as for \fG+\fR apply.
If an \fGint\fR or \fGchar\fR is subtracted
from a pointer, the
former is converted in the same way as explained under
\fG+\fR above.
.pg
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 \fGint\fR 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.
.ms
7.5  Shift operators
.et
The shift operators \fG<<\fR and \fG>>\fR group left-to-right.
.ms
7.5.1  \fIexpression \fG<< \fIexpression\fR
.br
7.5.2  \fIexpression \fG>> \fIexpression\fR
.et
Both operands must be \fGint\fR or \fGchar\fR,
and the result is \fGint\fR.
The second operand should
be non-negative.
The value of ``E1<<E2'' is E1 (interpreted as a bit
pattern 16 bits long) left-shifted E2 bits;
vacated bits are 0-filled.
The value of ``E1>>E2'' is E1 (interpreted as a two's
complement, 16-bit quantity) arithmetically
right-shifted E2 bit positions.
Vacated bits are filled by a copy of the sign bit of E1.
[Note: the use
of arithmetic rather than logical shift does not
survive transportation between machines.]
.ms
7.6  Relational operators
.et
The relational operators group left-to-right, but
this fact is not very useful; ``a<b<c'' does
not mean what it seems to.
.ms
7.6.1  \fIexpression \fG<\fI expression\fR
.br
.ne 4
7.6.2  \fIexpression \fG>\fI expression\fR
.br
.ne 4
7.6.3  \fIexpression \fG<=\fI expression\fR
.br
.ne 4
7.6.4  \fIexpression \fG>=\fI expression\fR
.et
The operators < (less than), > (greater than), <= (less than
or equal to) and >= (greater than or equal to)
all yield 0 if the specified relation is false
and 1 if it is true.
Operand conversion is exactly the same as for the \fG+\fR
operator except that pointers of any kind may be compared;
the result in this case depends on the relative
locations in storage of the pointed-to objects.
It does not seem to be very mean$ing$ful
to compare pointers with integers
other than 0.
.ms
.ti 0
7.7  Equality operators
.et
.ne 4
.ti 0
7.7.1  \fIexpression \fG==\fI expression\fR
.br
.ne 4
7.7.2  \fIexpression \fG!=\fI expression\fR
.et
The \fG==\fR (equal to) and the \fG!=\fR (not equal to) operators
are exactly analogous to the relational
operators except for their lower
precedence.
(Thus ``a<b@==@c<d'' is 1 whenever
a<b and c<d
have the same truth-value).
.ms
7.8  \fIexpression \fG&\fI expression\fR
.et
The \fG&\fR operator groups left-to-right.
Both operands must be \fGint\fR or \fGchar\fR;
the result is an \fGint\fR which is the bit-wise
logical \fGand\fR function of the operands.
.ms
.tr ^^
7.9  \fIexpression \fG^ \fIexpression\fR
.et
The \fG^\fR operator groups left-to-right.
The operands must be \fGint\fR or \fGchar\fR; the result is an \fGint\fR
which is the bit-wise exclusive \fGor\fR function of
its operands.
.tr ^\|
.ms
7.10  \fIexpression ^\(or \fIexpression\fR
.et
The \(or operator groups left-to-right.
The operands must be \fGint\fR or \fGchar\fR; the result is an \fGint\fR
which is the bit-wise inclusive \fGor\fR of its operands.
.ms
7.11  \fIexpression \fG&&\fI expression
.et
The \fG&&\fR operator returns 1 if both its operands
are non-zero, 0 otherwise.
Unlike \fG&\fR, \fG&&\fR guarantees left-to-right
evaluation; moreover the second operand is not evaluated
if the first operand is 0.
.pg
The operands need not have the same type, but each
must have one of the fundamental
types or be a pointer.
.ms
7.12  \fIexpression ^\(or\(or \fIexpression
.et
The ^\(or\(or operator returns 1 if either of its operands
is non-zero, and 0 otherwise.
Unlike ^\(or^,
^\(or\(or guarantees left-to-right evaluation; moreover,
the second operand is not evaluated
if the value of the first operand is non-zero.
.pg
The operands need not have the same type, but each
must
have one of the fundamental types
or be a pointer.
.ms
7.13  \fIexpression \fG? \fIexpression \fG:\fI expression\fR
.et
Conditional expressions group left-to-right.
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 the types of the second and third operand are the same, the
result has their common type;
otherwise the same conversion rules as for \fG+\fR
apply.
Only one of the second and third
expressions is evaluated.
.ms
7.14  Assignment operators
.et
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
of its left operand.
The value is the value stored in the
left operand after the assignment has taken place.
.ms
7.14.1  \fIlvalue \fG= \fIexpression\fR
.et
The value of the expression replaces that of the object
referred
to by the lvalue.
The operands need not have the same type, but
both must be
\fGint\fR, \fGchar\fR, \fGfloat\fR, \fGdouble\fR,
or pointer.
If neither operand is a pointer,
the assignment takes place as expected, possibly
preceded by conversion of the expression on the right.
.pg
When both operands are \fGint\fR
or pointers of any kind, no conversion
ever takes place;
the value of the expression is simply stored
into the object referred to by the lvalue.
Thus it is possible to
generate pointers which will cause addressing
exceptions when used.
.ms
.ta \w'0.00.00 'u
7.14.2	\fIlvalue \fG=+ \fIexpression\fR
.br
7.14.3	\fIlvalue \fG=\(mi \fIexpression\fR
.br
7.14.4	\fIlvalue \fG=\** \fIexpression\fR
.br
7.14.5	\fIlvalue \fG=/ \fIexpression\fR
.br
7.14.6	\fIlvalue \fG=% \fIexpression\fR
.br
7.14.7	\fIlvalue \fG=>> \fIexpression\fR
.br
7.14.8	\fIlvalue \fG=<< \fIexpression\fR
.br
7.14.9	\fIlvalue \fG=& \fIexpression\fR
.br
.tr ^^
7.14.10	\fIlvalue \fG=^ \fIexpression\fR
.br
.tr ^\|
7.14.11	\fIlvalue \fG=^\(or \fIexpression\fR
.et
The behavior of an expression
of the form ``E1@=op@E2'' may be inferred by
taking it as equivalent to ``E1@=@E1@op@E2'';
however, E1 is evaluated only once.
Moreover,
expressions like ``i@=+@p''
in which a pointer is added to an integer, are forbidden.
.ms
7.15  \fIexpression \fG,\fI expression\fR
.et
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.
It should be avoided in situations where comma is given
a special meaning, for example in actual arguments
to function calls (\(sc7.1.6) and lists of initializers (\(sc10.2).