(Pointers): Seversal clarifications.

(Pointer Arithmetic Low Level): rename to Low-Level Pointer Arithmetic.
This commit is contained in:
Richard Stallman 2022-09-15 15:47:40 -04:00
parent a441a65e8b
commit c0c0773fe5
1 changed files with 53 additions and 39 deletions

92
c.texi
View File

@ -324,7 +324,7 @@ Pointers
* Pointer Comparison:: Comparing memory address values.
* Pointer Arithmetic:: Computing memory address values.
* Pointers and Arrays:: Using pointer syntax instead of array syntax.
* Pointer Arithmetic Low Level:: More about computing memory address values.
* Low-Level Pointer Arithmetic:: More about computing memory address values.
* Pointer Increment/Decrement:: Incrementing and decrementing pointers.
* Pointer Arithmetic Drawbacks:: A common pointer bug to watch out for.
* Pointer-Integer Conversion:: Converting pointer types to integer types.
@ -4845,12 +4845,17 @@ Names}.
@chapter Pointers
@cindex pointers
Among high-level languages, C is rather low level, close to the
Among high-level languages, C is rather low-level, close to the
machine. This is mainly because it has explicit @dfn{pointers}. A
pointer value is the numeric address of data in memory. The type of
data to be found at that address is specified by the data type of the
pointer itself. The unary operator @samp{*} gets the data that a
pointer points to---this is called @dfn{dereferencing the pointer}.
pointer itself. Nothing in C can determine the ``correct'' data type
of data in memory; it can only blindly follow the data type of the
pointer you use to access the data.
The unary operator @samp{*} gets the data that a pointer points
to---this is called @dfn{dereferencing the pointer}. Its value
always has the type that the pointer points to.
C also allows pointers to functions, but since there are some
differences in how they work, we treat them later. @xref{Function
@ -4868,7 +4873,7 @@ Pointers}.
* Pointer Comparison:: Comparing memory address values.
* Pointer Arithmetic:: Computing memory address values.
* Pointers and Arrays:: Using pointer syntax instead of array syntax.
* Pointer Arithmetic Low Level:: More about computing memory address values.
* Low-Level Pointer Arithmetic:: More about computing memory address values.
* Pointer Increment/Decrement:: Incrementing and decrementing pointers.
* Pointer Arithmetic Drawbacks:: A common pointer bug to watch out for.
* Pointer-Integer Conversion:: Converting pointer types to integer types.
@ -4960,9 +4965,11 @@ double *aptrd[5]; /* @r{Array of five pointers to @code{double}.} */
@end example
@noindent
Because @samp{*} has higher syntactic precedence than subscripting,
you would subscript @code{aptrd} then dereference it. Therefore, it
declares an array of pointers, not a pointer.
Because @samp{*} has lower syntactic precedence than subscripting,
@samp{double *aptrd[5]} means, ``if you subscript @code{aptrd} by an
integer less than 5, then dereference it, you get a @code{double}.''
Therefore, @code{*aptrd[5]} declares an array of pointers, not a
pointer to an array.
@node Pointer Type Designators
@section Pointer-Type Designators
@ -4979,10 +4986,12 @@ double (*)[5] /* @r{Pointer to @code{double[5]}.} */
@end example
Remember, to understand what type a designator stands for, imagine the
variable name that would be in the declaration, and figure out what
type it would declare that variable with. @code{double (*)[5]} can
only come from @code{double (*@var{variable})[5]}, so it's a pointer
corresponding variable declaration with a variable name in it, and
figure out what type that variable would have. Thus, the type
designator @code{double (*)[5]} corresponds to the variable declaration
@code{double (*@var{variable})[5]}. That deciares a pointer variable
which, when dereferenced, gives an array of 5 @code{double}s.
So the type designator means, ``pointer to an array of 5 @code{double}s.''
@node Pointer Dereference
@section Dereferencing Pointers
@ -5232,10 +5241,10 @@ If one of the operands is @code{void *} (@pxref{Void Pointers}) and
the other is another pointer type, the comparison operator converts
the @code{void *} pointer to the other type so as to compare them.
(In standard C, this is not allowed if the other type is a function
pointer type, but that works in GNU C@.)
pointer type, but it works in GNU C@.)
Comparison operators also allow comparing the integer 0 with a pointer
value. Thus works by converting 0 to a null pointer of the same type
value. This works by converting 0 to a null pointer of the same type
as the other operand.
@node Pointer Arithmetic
@ -5331,10 +5340,10 @@ subtract_pointers ()
@}
@end example
The addition operation does not know where arrays are. All it does is
add the integer (multiplied by object size) to the value of the
pointer. When the initial pointer and the result point into a single
array, the result is well-defined.
The addition operation does not know where arrays begin or end in
memory. All it does is add the integer (multiplied by target object
size) to the numeric value of the pointer. When the initial pointer
and the result point into the same array, the result is well-defined.
@strong{Warning:} Only experts should do pointer arithmetic involving pointers
into different memory objects.
@ -5344,15 +5353,18 @@ The difference between two pointers has type @code{int}, or
declare it is to use the typedef name @code{ptrdiff_t} defined in the
file @file{stddef.h}.
This definition of pointer subtraction is consistent with
pointer-integer addition, in that @code{(p3 - p1) + p1} equals
@code{p3}, as in ordinary algebra.
C defines pointer subtraction to be consistent with pointer-integer
addition, so that @code{(p3 - p1) + p1} equals @code{p3}, as in
ordinary algebra. Pointer subtraction works by subtracting
@code{p1}'s numeric value from @code{p3}'s, and dividing by target
object size. The two pointer arguments should point into the same
array.
In standard C, addition and subtraction are not allowed on @code{void
*}, since the target type's size is not defined in that case.
Likewise, they are not allowed on pointers to function types.
However, these operations work in GNU C, and the ``size of the target
type'' is taken as 1.
type'' is taken as 1 byte.
@node Pointers and Arrays
@section Pointers and Arrays
@ -5374,26 +5386,26 @@ symmetrically, so one must be a pointer and the other an integer; it
does not matter which comes first.
Since indexing with square brackets is defined in terms of addition
and dereference, that too is symmetrical. Thus, you can write
and dereferencing, that too is symmetrical. Thus, you can write
@code{3[array]} and it is equivalent to @code{array[3]}. However, it
would be foolish to write @code{3[array]}, since it has no advantage
and could confuse people who read the code.
It may seem like a discrepancy that the definition @code{*(@var{a} +
@var{b})} requires a pointer, but @code{array[3]} uses an array value
@var{b})} requires a pointer, while @code{array[3]} uses an array value
instead. Why is this valid? The name of the array, when used by
itself as an expression (other than in @code{sizeof}), stands for a
pointer to the arrays's zeroth element. Thus, @code{array + 3}
pointer to the array's zeroth element. Thus, @code{array + 3}
converts @code{array} implicitly to @code{&array[0]}, and the result
is a pointer to element 3, equivalent to @code{&array[3]}.
Since square brackets are defined in terms of such addition,
Since square brackets are defined in terms of such an addition,
@code{array[3]} first converts @code{array} to a pointer. That's why
it works to use an array directly in that construct.
@node Pointer Arithmetic Low Level
@section Pointer Arithmetic at Low Level
@cindex pointer arithmetic, low level
@node Low-Level Pointer Arithmetic
@section Pointer Arithmetic at Low-Level
@cindex pointer arithmetic, low-level
@cindex low level pointer arithmetic
The behavior of pointer arithmetic is theoretically defined only when
@ -5407,7 +5419,8 @@ address, which is in fact an integer---call it @var{pint}. It treats
@var{i} as a number of elements of the type that @var{p} points to.
These elements' sizes add up to @code{@var{i} * sizeof (*@var{p})}.
So the sum, as an integer, is @code{@var{pint} + @var{i} * sizeof
(*@var{p})}. This value is reinterpreted as a pointer like @var{p}.
(*@var{p})}. This value is reinterpreted as a pointer of the same
type as @var{p}.
If the starting pointer value @var{p} and the result do not point at
parts of the same object, the operation is not officially legitimate,
@ -5448,7 +5461,8 @@ long} would always work, but it is cleaner to use @code{intptr_t}.)
The @samp{++} operator adds 1 to a variable. We have seen it for
integers (@pxref{Increment/Decrement}), but it works for pointers too.
For instance, suppose we have a series of positive integers,
terminated by a zero, and we want to add them all up.
terminated by a zero, and we want to add them up. Here is a simple
way to step forward through the array by advancing a pointer.
@example
int
@ -5481,12 +5495,12 @@ takes precedence over a prefix operator. Therefore, it dereferences
@code{p}, and increments @code{p} afterwards. Incrementing a variable
means adding 1 to it, as in @code{p = p + 1}. Since @code{p} is a
pointer, adding 1 to it advances it by the width of the datum it
points to---in this case, one @code{int}. Therefore, each iteration
points to---in this case, @code{sizeof (int)}. Therefore, each iteration
of the loop picks up the next integer from the series and puts it into
@code{next}.
This @code{for}-loop has no initialization expression since @code{p}
and @code{sum} are already initialized, it has no end-test since the
and @code{sum} are already initialized, has no end-test since the
@samp{break;} statement will exit it, and needs no expression to
advance it since that's done within the loop by incrementing @code{p}
and @code{sum}. Thus, those three expressions after @code{for} are
@ -5522,11 +5536,11 @@ and add it to @code{p}. (Recall that @code{p[i]} means @code{*(p +
i)}.) Either way, it uses the same address to get the next integer.
It makes no difference in this program whether we write @code{i++} or
@code{++i}, because the value is not used. All that matters is the
effect, to increment @code{i}.
@code{++i}, because the value @emph{of that expression} is not used.
We use it for its effect, to increment @code{i}.
The @samp{--} operator also works on pointers; it can be used
to scan backwards through an array, like this:
to step backwards through an array, like this:
@example
int
@ -5561,10 +5575,10 @@ memory. However, if you unintentionally adjust a pointer across the
bounds of the object and into some other object, the system has no way
to detect this error.
A bug which does that can easily result in clobbering part of another
object. For example, with @code{array[-1]} you can read or write the
nonexistent element before the beginning of an array---probably part
of some other data.
A bug which does that can easily result in clobbering (overwriting)
part of another object. For example, with @code{array[-1]} you can
read or write the nonexistent element before the beginning of an
array---probably part of some other data.
Combining pointer arithmetic with casts between pointer types, you can
create a pointer that fails to be properly aligned for its type. For