On 2/3/2012 02:11, Kaz Kylheku wrote:
> On 2012-02-03, Shao Miller<> wrote:
>> But for any stricter run-time bounds-checking, such as catching
>> 'a[i][j]' where the ranges for 'i' and 'j' aren't known at
>> translation-time and go out-of-bounds, there could be checks for each
>> dimension of a multi-dimensional array, but is that consistent with C?
>
> You know, who cares? All that matters is: is this check valuable to the user?
> Checks can be stronger or weaker than the standard language. Suppose that the
> C standard explicitly said that an array is just flat memory that can be
> aliased with any multi-dimensional array geometry. Well, someone might still
> want some of their code to pass array dimension bounds checks.
>
Absolutely it can be valuable. But if I write a program which I expect
to be strictly conforming and either translating it or running it
behaves differently for different implementations, that's upsetting.
>> It would seem unfair to give the array subscripting notation 'a[0][3]'
>> some kind of bounds-preferential treatment versus the identical '*(*(a +
>> 0) + 3)' notation.
>
> No, but the preferential treatment could actually stem from the
> "a + displacement" where a is not a pointer, but an array (that converts to a
> pointer on evaluation) and not from the choice of notation.
>
If that works, would you encourage and support a proposal to incorporate
that into Standard C? Maybe it's pretty reasonable to add something to
pointer arithmetic along the lines of "if the pointer was the immediate
result of the evaluation of an lvalue having an array type, then the
number of elements of the array object is the number of elements in that
array type."
> In such an expression, there is enough info to know that the displacement is in
> bounds with respect to the static type of a, regardless of the larger
> container in which that array finds itself.
>
And if we wish to "forget" about the bounds of array, would it be
reasonable for us to simply do:
int a[2][2] = { { 0 } };
int x;
x = ((int *) a[0])[3];
? Or maybe 'x = (1 ? a[0] : 0)[3];'? That seems easy.
>> But we do see references to "provenance" in at least one defect report,
>> and this seems related to the "provenance" of a pointer. If it "came
>> from" an array with certain boundaries, then pointer arithmetic is only
>> defined for its use with those boundaries, despite the fact that another
>> pointer with difference boundaries is identical in every other way.
>>
>> Of course "provenance" seems like a "gray area," since you can combine
>> things (such as via bit-wise operators). Then whence did they come?
>
> Clearly, at some point provenance has to be severed. A good rule of thumb (if
> provenance were to stop being a gray area) might be that a pointer value
> that is derived from a conversion from array, plus any combination of
> displacements, has provenance from that array. As soon as&..*.. is involved,
> it should be lost: e.g.&a[0] or&*(a + 0) ought to drop provenance.
Oh, ok. So when the evaluation of 'a' would yield a pointer value, the
bounds of the array object would be defined by the type of 'a', then you
could apply '*' and designate the object, then apply '&' and point to
that object without the previous bounds. Interesting! I guess that'd
require some changes to the text of '&' and '*'. Would you encourage
and support a proposal to incorporate that into Standard C?
I appreciate your discussion.

While you're here, could you clarify
if the following suggest undefined behaviour?
#1:
int a[2][2] { { 0 } };
int * p = a[0] + 0;
int * q = a[1] + 1;
ptrdiff_t diff = q - p;
#2:
union u_test {
int a[2][2];
int b[4];
};
union u_test test = { { { 0 } } };
int * p = test.a[1] + 1;
int * q = test.b + 3;
ptrdiff_t diff = q - p;
q = test.b + 0;
diff = q - p;
--
"The stationery store has moved. Aaargh!"