Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is pointer arithmetic allowed for malloc'ed blocks?

I was reading the following from the C standard:

(6.5.6 Additive operators)

9 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 result is the difference of the subscripts of the two array elements.

Now I wonder what is considered to be an "array object". To be more specific, I am wondering whether the following silly example is legal? Is that allocated memory block considered one "array object"?

uint8_t *data = malloc(255);
uint8_t *end = data + 255;
ptrdiff_t size = end - data;
like image 308
Julius Avatar asked Sep 06 '19 21:09

Julius


3 Answers

I couldn't find anything in the standard adequately defining exactly what constitues an 'array object', but looking at the memory allocation functions in 7.22.3 of the C11 standard draft, I did find this:

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).

It's not as explicit as one might want, but it does indicate that the memory returned from these functions can be used as an array, therefore the rules of pointer arithmetic should apply.

like image 100
Christian Gibbons Avatar answered Sep 24 '22 13:09

Christian Gibbons


For non-language-lawyer purposes, yes.

For language-lawyer purposes, I do not see that arithmetic is guaranteed with uint8_t, but it is with a character type (char, unsigned char, or signed char).

Per C 2018 7.22.3.4 2 and 3, if malloc does not return a null pointer then, the returned value points to allocated space for an object of the requested size. Per 3.15 1, an object is “region of data storage in the execution environment, the contents of which can represent values”. The space provided by malloc is a region of data storage in the execution environment, and its contents can represent values, even if they do not yet.

If we assigned the result of malloc to a pointer to a character type, 6.3.2.3 7 would apply: “… When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.” Although not explicitly stated, this is understood to mean the object may be treated as an array of character type, and this is required by other parts of the C standard, such as 6.5 6 (“If a value is copied into an object having no declared type … as an array of character type,…).

Thus, the pointer arithmetic operations are defined for pointers of type char *, unsigned char *, or signed char * on this object.

While uint8_t, if it is defined by <stdint.h>, must have largely the same properties as unsigned char (both are pure binary, uint8_t cannot be larger than unsigned char since unsigned char must support the value 255, and uint8_t cannot be smaller than unsigned char since the character types are by definition the fundamental units of object size), it is not necessary the same type. It could be an extended integer type, as permitted in 6.2.5 4, and thus might not be covered by the rules about converting pointers to character types.

like image 38
Eric Postpischil Avatar answered Sep 22 '22 13:09

Eric Postpischil


I think the relevant quote from the standard is from Section 7.22.3, "Memory management functions", paragraph 1:

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).

(emphasis mine.)

So the memory returned by malloc is an array, and calculating a pointer difference as you are is legal.

like image 32
1201ProgramAlarm Avatar answered Sep 22 '22 13:09

1201ProgramAlarm