(Primitive Types): Many cleanups.
This commit is contained in:
parent
52c0123371
commit
778ce9a752
126
c.texi
126
c.texi
|
@ -1829,9 +1829,9 @@ Arithmetic operators in C attempt to be as similar as possible to the
|
|||
abstract arithmetic operations, but it is impossible to do this
|
||||
perfectly. Numbers in a computer have a finite range of possible
|
||||
values, and non-integer values have a limit on their possible
|
||||
accuracy. Nonetheless, in most cases you will encounter no surprises
|
||||
in using @samp{+} for addition, @samp{-} for subtraction, and @samp{*}
|
||||
for multiplication.
|
||||
accuracy. Nonetheless, except when results are out of range, you will
|
||||
encounter no surprises in using @samp{+} for addition, @samp{-} for
|
||||
subtraction, and @samp{*} for multiplication.
|
||||
|
||||
Each C operator has a @dfn{precedence}, which is its rank in the
|
||||
grammatical order of the various operators. The operators with the
|
||||
|
@ -2102,19 +2102,19 @@ But sometimes it matters precisely where the conversion occurs.
|
|||
|
||||
If @code{i} and @code{j} are integers, @code{(i + j) * 2.0} adds them
|
||||
as an integer, then converts the sum to floating point for the
|
||||
multiplication. If the addition gets an overflow, that is not
|
||||
equivalent to converting both integers to floating point and then
|
||||
adding them. You can get the latter result by explicitly converting
|
||||
the integers, as in @code{((double) i + (double) j) * 2.0}.
|
||||
@xref{Explicit Type Conversion}.
|
||||
multiplication. If the addition causes an overflow, that is not
|
||||
equivalent to converting each integer to floating point and then
|
||||
adding the two floating point numbers. You can get the latter result
|
||||
by explicitly converting the integers, as in @code{((double) i +
|
||||
(double) j) * 2.0}. @xref{Explicit Type Conversion}.
|
||||
|
||||
@c Eggert's report
|
||||
Adding or multiplying several values, including some integers and some
|
||||
floating point, does the operations left to right. Thus, @code{3.0 +
|
||||
floating point, performs the operations left to right. Thus, @code{3.0 +
|
||||
i + j} converts @code{i} to floating point, then adds 3.0, then
|
||||
converts @code{j} to floating point and adds that. You can specify a
|
||||
different order using parentheses: @code{3.0 + (i + j)} adds @code{i}
|
||||
and @code{j} first and then adds that result (converting to floating
|
||||
and @code{j} first and then adds that sum (converted to floating
|
||||
point) to 3.0. In this respect, C differs from other languages, such
|
||||
as Fortran.
|
||||
|
||||
|
@ -2271,7 +2271,7 @@ The left operand is the value to be shifted, and the right operand
|
|||
says how many bits to shift it (the @dfn{shift count}). The left
|
||||
operand is promoted (@pxref{Operand Promotions}), so shifting never
|
||||
operates on a narrow integer type; it's always either @code{int} or
|
||||
wider. The value of the shift operator has the same type as the
|
||||
wider. The result of the shift operation has the same type as the
|
||||
promoted left operand.
|
||||
|
||||
@menu
|
||||
|
@ -2322,12 +2322,12 @@ number of bits gives machine-dependent results.
|
|||
@subsection Caveats for Shift Operations
|
||||
|
||||
@strong{Warning:} If the shift count is greater than or equal to the
|
||||
width in bits of the first operand, the results are machine-dependent.
|
||||
Logically speaking, the ``correct'' value would be either -1 (for
|
||||
right shift of a negative number) or 0 (in all other cases), but what
|
||||
it really generates is whatever the machine's shift instruction does in
|
||||
that case. So unless you can prove that the second operand is not too
|
||||
large, write code to check it at run time.
|
||||
width in bits of the promoted first operand, the results are
|
||||
machine-dependent. Logically speaking, the ``correct'' value would be
|
||||
either @minus{}1 (for right shift of a negative number) or 0 (in all other
|
||||
cases), but the actual result is whatever the machine's shift
|
||||
instruction does in that case. So unless you can prove that the
|
||||
second operand is not too large, write code to check it at run time.
|
||||
|
||||
@strong{Warning:} Never rely on how the shift operators relate in
|
||||
precedence to other arithmetic binary operators. Programmers don't
|
||||
|
@ -3302,11 +3302,12 @@ on the left and one on the right.
|
|||
|
||||
All the binary operators in C are syntactically left-associative.
|
||||
This means that @w{@code{a @var{op} b @var{op} c}} means @w{@code{(a
|
||||
@var{op} b) @var{op} c}}. However, you should only write repeated
|
||||
operators without parentheses using @samp{+}, @samp{-}, @samp{*} and
|
||||
@samp{/}, because those cases are clear from algebra. So it is ok to
|
||||
write @code{a + b + c} or @code{a - b - c}, but never @code{a == b ==
|
||||
c} or @code{a % b % c}.
|
||||
@var{op} b) @var{op} c}}. However, the only operators you should
|
||||
repeat in this way without parentheses are @samp{+}, @samp{-},
|
||||
@samp{*} and @samp{/}, because those cases are clear from algebra. So
|
||||
it is ok to write @code{a + b + c} or @code{a - b - c}, but never
|
||||
@code{a == b == c} or @code{a % b % c}. For those operators, use
|
||||
explicit parentheses to show how the operations nest.
|
||||
|
||||
Each C operator has a @dfn{precedence}, which is its rank in the
|
||||
grammatical order of the various operators. The operators with the
|
||||
|
@ -3522,7 +3523,7 @@ carried out before calling the function.
|
|||
The ordering imposed by a sequence point applies locally to a limited
|
||||
range of code, as stated above in each case. For instance, the
|
||||
ordering imposed by the comma operator does not apply to code outside
|
||||
that comma operator. Thus, in this code,
|
||||
the operands of that comma operator. Thus, in this code,
|
||||
|
||||
@example
|
||||
(x = 5, foo (x)) + x * x
|
||||
|
@ -3538,11 +3539,11 @@ them.
|
|||
@cindex postincrement and ordering
|
||||
@cindex ordering and postincrement
|
||||
|
||||
Ordering requirements are loose with the postincrement and
|
||||
postdecrement operations (@pxref{Postincrement/Postdecrement}), which
|
||||
specify side effects to happen ``a little later.'' They must happen
|
||||
before the next sequence point, but that still leaves room for various
|
||||
meanings. In this expression,
|
||||
The ordering requirements for the postincrement and postdecrement
|
||||
operations (@pxref{Postincrement/Postdecrement}) are loose: those side
|
||||
effects must happen ``a little later,'' before the next sequence
|
||||
point. That still leaves room for various orders that give different
|
||||
results. In this expression,
|
||||
|
||||
@example
|
||||
z = x++ - foo ()
|
||||
|
@ -3561,11 +3562,16 @@ x = x++
|
|||
|
||||
@noindent
|
||||
@code{x} will certainly be incremented but the incremented value may
|
||||
not stick. If the incrementation of @code{x} happens after the
|
||||
assignment to @code{x}, the incremented value will remain in place.
|
||||
But if the incrementation happens first, the assignment will overwrite
|
||||
that with the not-yet-incremented value, so the expression as a whole
|
||||
will leave @code{x} unchanged.
|
||||
be replaced with the old value. That's because the incrementation and
|
||||
the assignment may occur in either oder. If the incrementation of
|
||||
@code{x} occurs after the assignment to @code{x}, the incremented
|
||||
value will remain in place. But if the incrementation happens first,
|
||||
the assignment will put the not-yet-incremented value back into
|
||||
@code{x}, so the expression as a whole will leave @code{x} unchanged.
|
||||
|
||||
The conclusion: @strong{avoid such expressions}. Take care, when you
|
||||
use postincrement and postdecrement, that the specific expression you
|
||||
use is not ambiguous as to order of execution.
|
||||
|
||||
@node Ordering of Operands
|
||||
@section Ordering of Operands
|
||||
|
@ -3583,14 +3589,15 @@ followed by the other. Any side effects in the operand that's computed
|
|||
first are executed before the other operand is computed.
|
||||
|
||||
@item
|
||||
That applies to assignment operators too, except that in simple assignment
|
||||
That applies to assignment operators too, except that, in simple assignment,
|
||||
the previous value of the left operand is unused.
|
||||
|
||||
@item
|
||||
The arguments in a function call can be computed in any order, but
|
||||
they can't be intermixed. Thus, one argument is fully computed, then
|
||||
another, and so on until they are all done. Any side effects in one argument
|
||||
are executed before computation of another argument begins.
|
||||
another, and so on until they have all been done. Any side effects in
|
||||
one argument are executed before computation of another argument
|
||||
begins.
|
||||
@end itemize
|
||||
|
||||
These rules don't cover side effects caused by postincrement and
|
||||
|
@ -3598,11 +3605,11 @@ postdecrement operators---those can be deferred up to the next
|
|||
sequence point.
|
||||
|
||||
If you want to get pedantic, the fact is that GCC can reorder the
|
||||
computations in many other ways provided that doesn't alter the result
|
||||
of running the program. However, because they don't alter the result
|
||||
of running the program, they are negligible, unless you are concerned
|
||||
computations in many other ways provided that it doesn't alter the result
|
||||
of running the program. However, because it doesn't alter the result
|
||||
of running the program, it is negligible, unless you are concerned
|
||||
with the values in certain variables at various times as seen by other
|
||||
processes. In those cases, you can use @code{volatile} to prevent
|
||||
processes. In those cases, you should use @code{volatile} to prevent
|
||||
optimizations that would make them behave strangely. @xref{volatile}.
|
||||
|
||||
@node Optimization and Ordering
|
||||
|
@ -3694,8 +3701,8 @@ represent both positive and negative numbers, in a range spread almost
|
|||
equally on both sides of zero.
|
||||
|
||||
Aside from signedness, the integer data types vary in size: how many
|
||||
bytes long they are. The size determines how many different integer
|
||||
values the type can hold.
|
||||
bytes long they are. The size determines the range of integer values
|
||||
the type can hold.
|
||||
|
||||
Here's a list of the signed integer data types, with the sizes they
|
||||
have on most computers. Each has a corresponding unsigned type; see
|
||||
|
@ -3704,7 +3711,8 @@ have on most computers. Each has a corresponding unsigned type; see
|
|||
@table @code
|
||||
@item signed char
|
||||
One byte (8 bits). This integer type is used mainly for integers that
|
||||
represent characters, as part of arrays or other data structures.
|
||||
represent characters, usually as elements of arrays or fields of other
|
||||
data structures.
|
||||
|
||||
@item short
|
||||
@itemx short int
|
||||
|
@ -3775,8 +3783,8 @@ In particular, if the value is really a character, you should declare
|
|||
the variable @code{int}. Not @code{char}! Using that narrow type can
|
||||
force the compiler to truncate values for conversion, which is a
|
||||
waste. Furthermore, some functions return either a character value,
|
||||
or @minus{}1 for ``no character.'' Using @code{int} keeps those
|
||||
values distinct.
|
||||
or @minus{}1 for ``no character.'' Using @code{int} makes it possible
|
||||
to distinguish @minus{}1 from a character by sign.
|
||||
|
||||
The narrow integer types are useful as parts of other objects, such as
|
||||
arrays and structures. Compare these array declarations, whose sizes
|
||||
|
@ -3867,10 +3875,11 @@ given previously (@pxref{Basic Integers}).
|
|||
|
||||
To be completely sure of the size of an integer type,
|
||||
use the types @code{int16_t}, @code{int32_t} and @code{int64_t}.
|
||||
Their corresponding unsigned types add @samp{u} at the front.
|
||||
To define these, include the header file @file{stdint.h}.
|
||||
Their corresponding unsigned types add @samp{u} at the front:
|
||||
@code{uint16_t}, @code{uint32_t} and @code{uint64_t}.
|
||||
To define all these types, include the header file @file{stdint.h}.
|
||||
|
||||
The GNU C Compiler compiles for some embedded controllers that use two
|
||||
The GNU C Compiler can compile for some embedded controllers that use two
|
||||
bytes for @code{int}. On some, @code{int} is just one ``byte,'' and
|
||||
so is @code{short int}---but that ``byte'' may contain 16 bits or even
|
||||
32 bits. These processors can't support an ordinary operating system
|
||||
|
@ -3886,8 +3895,11 @@ programs do not try to support them.
|
|||
@findex long double
|
||||
|
||||
@dfn{Floating point} is the binary analogue of scientific notation:
|
||||
internally it represents a number as a fraction and a binary exponent; the
|
||||
value is that fraction multiplied by the specified power of 2.
|
||||
internally it represents a number as a fraction and a binary exponent;
|
||||
the value is that fraction multiplied by the specified power of 2.
|
||||
(The C standard nominally permits other bases, but in GNU C the base
|
||||
is always 2.)
|
||||
@c ???
|
||||
|
||||
For instance, to represent 6, the fraction would be 0.75 and the
|
||||
exponent would be 3; together they stand for the value @math{0.75 * 2@sup{3}},
|
||||
|
@ -4025,8 +4037,9 @@ print_if_positive (double x, double y)
|
|||
@}
|
||||
@end example
|
||||
|
||||
A @code{void}-returning function is comparable to what some other languages
|
||||
call a ``procedure'' instead of a ``function.''
|
||||
A @code{void}-returning function is comparable to what some other
|
||||
languages (for instance, Fortran and Pascal) call a ``procedure''
|
||||
instead of a ``function.''
|
||||
|
||||
@c ??? Already presented
|
||||
@c @samp{%f} in an output template specifies to format a @code{double} value
|
||||
|
@ -4039,9 +4052,10 @@ Beyond the primitive types, C provides several ways to construct new
|
|||
data types. For instance, you can define @dfn{pointers}, values that
|
||||
represent the addresses of other data (@pxref{Pointers}). You can
|
||||
define @dfn{structures}, as in many other languages
|
||||
(@pxref{Structures}), and @dfn{unions}, which specify multiple ways
|
||||
to look at the same memory space (@pxref{Unions}). @dfn{Enumerations}
|
||||
are collections of named integer codes (@pxref{Enumeration Types}).
|
||||
(@pxref{Structures}), and @dfn{unions}, which define multiple ways to
|
||||
interpret the contents of the same memory space (@pxref{Unions}).
|
||||
@dfn{Enumerations} are collections of named integer codes
|
||||
(@pxref{Enumeration Types}).
|
||||
|
||||
@dfn{Array types} in C are used for allocating space for objects,
|
||||
but C does not permit operating on an array value as a whole. @xref{Arrays}.
|
||||
|
@ -4053,7 +4067,7 @@ but C does not permit operating on an array value as a whole. @xref{Arrays}.
|
|||
Some C constructs require a way to designate a specific data type
|
||||
independent of any particular variable or expression which has that
|
||||
type. The way to do this is with a @dfn{type designator}. The
|
||||
constucts that need one include casts (@pxref{Explicit Type
|
||||
constructs that need one include casts (@pxref{Explicit Type
|
||||
Conversion}) and @code{sizeof} (@pxref{Type Size}).
|
||||
|
||||
We also use type designators to talk about the type of a value in C,
|
||||
|
|
Loading…
Reference in New Issue