[ Pobierz całość w formacie PDF ]
unsigned long int, the other is converted to unsigned long int.
" Otherwise, if one operand is long int and the other is unsigned int, the effect depends on
whether a long int can represent all values of an unsigned int; if so, the unsigned int
operand is converted to long int; if not, both are converted to unsigned long int.
" Otherwise, if one operand is long int, the other is converted to long int.
" Otherwise, if either operand is unsigned int, the other is converted to unsigned int.
" Otherwise, both operands have type int.
There are two changes here. First, arithmetic on float operands may be done in single precision, rather than double; the
first edition specified that all floating arithmetic was double precision. Second, shorter unsigned types, when combined
with a larger signed type, do not propagate the unsigned property to the result type; in the first edition, the unsigned
always dominated. The new rules are slightly more complicated, but reduce somewhat the surprises that may occur when
an unsigned quantity meets signed. Unexpected results may still occur when an unsigned expression is compared to a
signed expression of the same size.
A.6.2 Integral Conversions 176
The C programming Language
A.6.6 Pointers and Integers
An expression of integral type may be added to or subtracted from a pointer; in such a case the integral
expression is converted as specified in the discussion of the addition operator (Par.A.7.7).
Two pointers to objects of the same type, in the same array, may be subtracted; the result is converted to an
integer as specified in the discussion of the subtraction operator (Par.A.7.7).
An integral constant expression with value 0, or such an expression cast to type void *, may be converted,
by a cast, by assignment, or by comparison, to a pointer of any type. This produces a null pointer that is equal
to another null pointer of the same type, but unequal to any pointer to a function or object.
Certain other conversions involving pointers are permitted, but have implementation-defined aspects. They
must be specified by an explicit type-conversion operator, or cast (Pars.A.7.5 and A.8.8).
A pointer may be converted to an integral type large enough to hold it; the required size is
implementation-dependent. The mapping function is also implementation-dependent.
A pointer to one type may be converted to a pointer to another type. The resulting pointer may cause
addressing exceptions if the subject pointer does not refer to an object suitably aligned in storage. It is
guaranteed that a pointer to an object may be converted to a pointer to an object whose type requires less or
equally strict storage alignment and back again without change; the notion of ``alignment'' is
implementation-dependent, but objects of the char types have least strict alignment requirements. As
described in Par.A.6.8, a pointer may also be converted to type void * and back again without change.
A pointer may be converted to another pointer whose type is the same except for the addition or removal of
qualifiers (Pars.A.4.4, A.8.2) of the object type to which the pointer refers. If qualifiers are added, the new
pointer is equivalent to the old except for restrictions implied by the new qualifiers. If qualifiers are removed,
operations on the underlying object remain subject to the qualifiers in its actual declaration.
Finally, a pointer to a function may be converted to a pointer to another function type. Calling the function
specified by the converted pointer is implementation-dependent; however, if the converted pointer is
reconverted to its original type, the result is identical to the original pointer.
A.6.7 Void
The (nonexistent) value of a void object may not be used in any way, and neither explicit nor implicit
conversion to any non-void type may be applied. Because a void expression denotes a nonexistent value, such
an expression may be used only where the value is not required, for example as an expression statement
(Par.A.9.2) or as the left operand of a comma operator (Par.A.7.18).
An expression may be converted to type void by a cast. For example, a void cast documents the discarding
of the value of a function call used as an expression statement.
void did not appear in the first edition of this book, but has become common since.
A.6.8 Pointers to Void
Any pointer to an object may be converted to type void * without loss of information. If the result is
converted back to the original pointer type, the original pointer is recovered. Unlike the pointer-to-pointer
A.6.6 Pointers and Integers 177
The C programming Language
conversions discussed in Par.A.6.6, which generally require an explicit cast, pointers may be assigned to and
from pointers of type void *, and may be compared with them.
This interpretation of void * pointers is new; previously, char * pointers played the role of generic pointer. The ANSI
standard specifically blesses the meeting of void * pointers with object pointers in assignments and relationals, while
requiring explicit casts for other pointer mixtures.
A.7 Expressions
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 + (Par.A.7.7) are
those expressions defined in Pars.A.7.1-A.7.6. Within each subsection, the operators have the same
precedence. Left- or right-associativity is specified in each subsection for the operators discussed therein.
The grammar given in Par.13 incorporates the precedence and associativity of the operators.
The precedence and associativity of operators is fully specified, but the order of evaluation of expressions is,
with certain exceptions, undefined, even if the subexpressions involve side effects. That is, unless the
definition of the operator guarantees that its operands are evaluated in a particular order, the implementation is
free to evaluate operands in any order, or even to interleave their evaluation. However, each operator
combines the values produced by its operands in a way compatible with the parsing of the expression in which
it appears.
This rule revokes the previous freedom to reorder expressions with operators that are mathematically commutative and
associative, but can fail to be computationally associative. The change affects only floating-point computations near the
limits of their accuracy, and situations where overflow is possible.
The handling of overflow, divide check, and other exceptions in expression evaluation is not defined by the
language. Most existing implementations of C ignore overflow in evaluation of signed integral expressions
and assignments, but this behavior is not guaranteed. Treatment of division by 0, and all floating-point
exceptions, varies among implementations; sometimes it is adjustable by a non-standard library function.
A.7.1 Pointer Conversion
If the type of an expression or subexpression is ``array of T,'' for some type T, then the value of the expression
is a pointer to the first object in the array, and the type of the expression is altered to ``pointer to T.'' This
conversion does not take place if the expression is in the operand of the unary & operator, or of ++, --,
sizeof, or as the left operand of an assignment operator or the . operator. Similarly, an expression of type
``function returning T,'' except when used as the operand of the & operator, is converted to ``pointer to
function returning T.''
A.7.2 Primary Expressions
Primary expressions are identifiers, constants, strings, or expressions in parentheses.
primary-expression
identifier
constant
string
(expression)
A.7 Expressions 178
The C programming Language
An identifier is a primary expression, provided it has been suitably declared as discussed below. Its type is
[ Pobierz całość w formacie PDF ]