JTC1/SC22/WG14
N901
WG14/N901
C99 Defect Reports
Author: Clive Feather <clive@demon.net>
Date: 1999-10-21
Item 1
Subject: lacuna in pointer arithmetic
Problem
-------
Consider the code extract:
int v [10];
int p = (v + 9) + 1;
int q = v + 10;
The relevant part of 6.5.6 paragraph 8 reads:
If the pointer operand points to an
element of an array object, and the array is large enough,
the result points to an element offset from the original
element such that the difference of the subscripts of the
resulting and original array elements equals the integer
expression. In other words, if the expression P points to
the i-th element of an array object, the expressions (P)+N
(equivalently, N+(P)) and (P)-N (where N has the value n)
point to, respectively, the i+n-th and i-n-th elements of
the array object, provided they exist. Moreover, if the
expression P points to the last element of an array object,
the expression (P)+1 points one past the last element of the
array object, and if the expression Q points one past the
last element of an array object, the expression (Q)-1 points
to the last element of the array object. If both the
pointer operand and the result point to elements of the same
array object, or one past the last element of the array
object, the evaluation shall not produce an overflow;
otherwise, the behavior is undefined.
There is a problem with this wording in that it defines arithmetic
of pointers within the array object properly, but it only defines
arithmetic to "one past the end" when the pointer was previously to
the last object. In other words, the initialization of p is correct
because (v + 9) points to the last element of an array, but the
initialization of q is not because the "i+n-th" element does not
exist.
It is clear that these constructs are supposed to work, and that the
relevant wording just needs to be adjusted.
Suggested Technical Corrigendum
-------------------------------
Change the cited text to:
If the pointer operand points to an element of an array object
or to one past the last element of the array object, and the
the array is large enough, the result points to an element, or
to the location one past the last element, offset from the
original element such that the difference of the subscripts of the
resulting and original array elements equals the integer
expression. In other words, if the expression P points to
the i-th element of an array object with k elements, or to one
past the last element (in which case i equals k), then the
expressions (P)+N and N+(P), (where N has the value n which may
be positive, zero, or negative) both point to the i+n-th elements
of the array object, provided it exists, or if i+n equals k, to
one past the last element of the array object. If both the
pointer operand and the result point to elements of the same
array object, or one past the last element of the array
object (that is, both i and i+n lie between 0 and k inclusive),
the evaluation shall not produce an overflow; otherwise, the
behavior is undefined.
Similarly, change the following text in paragraph 9:
In other words, if the
expressions P and Q point to, respectively, the i-th and j-
th elements of an array object, the expression (P)-(Q) has
the value i-j provided the value fits in an object of type
ptrdiff_t. Moreover, if the expression P points either to
an element of an array object or one past the last element
of an array object, and the expression Q points to the last
element of the same array object, the expression ((Q)+1)-(P)
has the same value as ((Q)-(P))+1 and as -((P)-((Q)+1)), and
has the value zero if the expression P points one past the
last element of the array object, even though the expression
(Q)+1 does not point to an element of the array object.88)
to:
In other words, if the expressions P and Q point to,
respectively, the i-th and j-th elements of an array object
with k elements, or to one past the last element (in which
case i or j, or both, equals k), the expression (P)-(Q) has
the value i-j provided the value fits in an object of type
ptrdiff_t.88)
Item 2
Subject: partially initialized structures
Problem
-------
Consider the code extract:
struct listheader
{
struct item *head;
struct item *tail;
};
// The following is at block scope
struct listheader h1;
h1.head = NULL;
struct listheader h2;
h2 = h1;
The value of h1.tail is indeterminate throughout, but provided that
the code never accesses it this is not a problem. However, if it holds
a trap representation, the assignment to h2 involves assigning a trap
representation, which is undefined behaviour.
There are two possible resolutions:
(1) Say that the code is defined. Any implementation that uses
memberwise copying of structures now has to explicitly disable
detection of trap values.
(2) Say that the code is undefined. This is going to surprise a number
of people.