On 26.05.2012 05:35, Walter Bright wrote:
On 5/25/2012 8:24 PM, Don wrote:
The problem is, if pstart and pend point to the beginning and end of
an array,
then given another pointer q, there is AFAIK no defined way in C for
checking if
q is between pstart and pend, even though I'm sure everyone does it.
(eg, I
don't know how to implement memcpy otherwise).
If q is part of that array, (q >= pstart && q <= pend) is
well-defined, and
returns true.
But if it isn't part of that array, q >= pstart is undefined.
In reality of course, if q is unrelated to the array then EITHER q <
pstart, OR
q > pend. So (q >= pstart && q <= pend) is ALWAYS false, and the
result is
completely predictable.
If q is unrelated to the array, which you can tell because q, pstart,
and pend must all refer to the same object that CTFE knows about, then
you can have CTFE refuse to execute it.
Yes, that's what happens now. But that doesn't help the programmer.
If it is inside, no problem, the expression is true. But if it is not
inside, the expression is not false -- it's a compile-time error.
So you can't use it as a test for if it is inside the same object.
I was confused about how memmove can work in C without relying on
undefined behaviour. But I just read
http://www.cplusplus.com/reference/clibrary/cstring/memcpy/
which defines it in terms of an intermediate buffer.
So maybe, the current CTFE implementation is _exactly_ consistent with
the C spec. If that's true, though, I find it pretty incredible that
there is no way to find out if a pointers points a particular array,
even if you have pointers to both the start and end of that array.
(OK, I guess you can iterate from start to end, checking for equality,
but .. bleah .. it's a terrible abstraction inversion).
ie, the full expression can be well-defined even though its two
subexpressions
are not.
This can be implemented.
Given an expression like q >= pstart, where p and q are unrelated,
it's possible
to make it have the value 'false_or_undefined'. If it is anded with
another
expression that is also false_or_undefined, and goes the other
direction ( q <=
pend) , then the whole thing is false. Otherwise, it generates an error.
The reason it would have to be a special case is because of things like:
bool b = false;
q >= start && ( b = true, true) && q <= end
which is undefined because the result of the first comparison has been
stored.
So it would only be valid for
one-comparison-in-each-direction-anded-together
(and the equivalent for ||).
I still don't think you need to make a special case for it. If upon
initialization of q, pstart, and pend, CTFE makes a note of what memory
object they are initialized from, then you can unambiguously tell if
they still point within the same object or not.