home *** CD-ROM | disk | FTP | other *** search
- .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).
-