iBug iBug - 11 months ago 84
C Question

Is it well-defined to use a pointer pointing to one-past-malloc?

In C, it is perfectly well to make a pointer that points to one past the last element of an array and use it in pointer arithmetics, as long as you don't dereference it:

int a[5], *p = a+5, diff = p-a; // Well-defined


However, these are UBs:

p = a+6;
int b = *(a+5), diff = p-a; // Dereferencing and pointer arithmetic


Now I have a question: Does this apply to dynamically allocated memory? Assume I'm only using a pointer pointing to one-past-the-last in pointer arithmetics, without dereferencing it, and
malloc()
succeeds.

int *a = malloc(5 * sizeof(*a));
assert(a != NULL, "Memory allocation failed");
// Question:
int *p = a+5;
int diff = p-a; // Use in pointer arithmetic?

Answer Source

Is it well-defined to use a pointer pointing to one-past-malloc?

It is well defined if p is pointing to one past the allocated memory and it is not dereferenced.

n1570 - §6.5.6 (p8):

[...] If the result points one past the last element of the array object, it shall not be used as the operand of a unary * operator that is evaluated.

Subtracting two pointers are valid only when they point to elements of the same array object or one past the last element of the array object, otherwise it will result in undefined behavior.

(p9):

When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object [...]

The above quotes are well applicable for both dynamically and statically allocated memory.

int a[5];
ptrdiff_t diff = &a[5] - &a[0]; // Well-defined

int *d = malloc(5 * sizeof(*d));
assert(d != NULL, "Memory allocation failed");
diff = &d[5] - &d[0];        // Well-defined

Another reason that this is valid for dynamically allocated memory, as pointed by Jonathan Leffler in a comment is:

§7.22.3 (p1):

The order and contiguity of storage allocated by successive calls to the aligned_alloc, calloc, malloc, and realloc functions is unspecified. The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly deallocated).

The pointer returned by malloc in the above snippet is assigned to d and the memory allocated is an array of 5 int objects.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download