Is D's pointer subtraction more permissive than C (and C++)?
Ali Çehreli
acehreli at yahoo.com
Fri Apr 1 15:52:39 UTC 2022
As the following quote from a Microsoft document claims, and as I've
already known, pointer subtraction is legal only if the pointers are
into the same array: "ANSI 3.3.6, 4.1.1 The type of integer required to
hold the difference between two pointers to elements of the same array,
ptrdiff_t." (
https://docs.microsoft.com/en-us/cpp/c-language/pointer-subtraction?view=msvc-170
)
I suspect "array" means "a block of memory" there because arrays are
ordinarily malloc'ed pieces of memory in C.
1) Is D more permissive (or anemic in documentation:))? I ask because
paragraph 5 below does not mention the pointers should be related in any
way:
https://dlang.org/spec/expression.html#pointer_arithmetic
2) Is subtracting pointers that used to be in the same array legal.
void main() {
auto a = [ 1, 2 ];
auto b = a;
assert(a.ptr - b.ptr == 0); // i) Obviously legal?
// Drop the first element
a = a[1..$];
assert(a.ptr - b.ptr == 1); // ii) GC-behaviorally legal?
// Save the pointer
const old_aPtr = a.ptr;
// and move the array to another memory
a.length = 1_000_000;
// Expect a and b are on different blocks of memory
assert(a.ptr != old_aPtr);
assert(old_aPtr - b.ptr == 1); // iii) Practically legal?
}
Regardless of your answer, I will go ahead and perform that last
subtraction :).
Ali
P.S. I am trying to implement a type where slices will follow the
elements as the elements may be moved in memory:
const old_aPtr = a.ptr;
a ~= e;
if (a.ptr != old_aPtr) {
// Elements are moved; adjust the slice
assert(b.ptr >= old_aPtr);
const old_bOffset = b.ptr - old_aPtr;
b = a[old_bOffset .. $];
}
If you ask why I don't keep offsets instead of slices to begin with, I
want to use pointers (implicitly in D slices) so that they participate
in the ownership of array elements so that the GC does not free earlier
elements as the buffer is popFronted as well.
More information about the Digitalmars-d
mailing list