Suppose I do something as follows:
size_t length = 1000;
char* p = malloc(length);
and then I want to loop over the elements, so most basic would be:
for (size_t i = 0; i < length; ++i) {
p[i] = ...; // or p[length - 1 - i] = ...
}
but also possible is
char* q = p;
for (size_t i = 0; i < length; ++i) {
*q = ...;
++q;
}
or in reverse
char* q = p + (length - 1);
for (size_t i = 0; i < length; ++i) {
*q = ...;
--q;
}
My question is, what if I want to avoid the i and do something as follows:
char* const final = p + (length - 1);
for (char* q = p; q <= final; ++q) {
*q = ...;
}
or in reverse:
char* const final = p + (length - 1);
for (char* q = final; q >= p; --q) {
*q = ...;
}
It seems that there is a very tiny chance of erroneous behavior in those loops avoiding i; for the first loop, what if p + length == 0, i.e. we have a system where we were allocated memory just at the very end of the possible size_t limit and overflow happened... For the second loop, what if p == 0, i.e. we have a system where we were allocated memory just at the beginning of memory... In both these scenarios the loop will not end when needed...
Probably those do not really happen, but if this is undefined behavior then maybe it is better to loop with the i although it looks slightly less elegant..
Edit: Following Fe2O3's comment, I recalled that indeed I wanted to ask it a bit differently. Namely, I would like not an array of chars, but an array of elements of some struct type, so the struct is potentially relatively big, of size 3000, say. Then it is enough for p to be < 3000 in order for the second loop to fail, it is not necessary for it to be 0. Also, it is enough for final to be at the maximum size minus 3000... Of course, 3000 can be even bigger...
0is, in most implementations, equivalent to(void*)0, orNULL. That's the "special indication" that allocation failed. So it cannot be used to simultaneously indicate a successful allocation. At the other end, the 'heap' boundary cannot bleed into thestackthat is located at the most high addresses. In other words, this is not a concern...p + lengthis always correct according to the Standard. For the 2nd situation usedo ... while(q-- > p);for (char* q = final +1; q-- > p; )... It is UB to decrementqto a value less thanp, and then compare the two pointers...p + lengthis always correct as a pointer (eg for pointer comparisons) ... not correct if you dereference it:*(p + length)is invalid!