malloc 块是否允许指针运算?

Is pointer arithmetic allowed for malloc'ed blocks?

我正在阅读 C 标准中的以下内容:

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

现在我想知道什么是 "array object"。更具体地说,我想知道以下愚蠢的例子是否合法?分配的内存块是否被认为是一个 "array object"?

uint8_t *data = malloc(255);
uint8_t *end = data + 255;
ptrdiff_t size = end - data;

我在标准中找不到任何内容来充分定义什么构成了 'array object',但是查看 C11 标准草案 7.22.3 中的内存分配函数,我确实发现了这个:

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

它并不像人们想要的那样明确,但它确实表明从这些函数返回的内存可以用作数组,因此指针算法的规则应该适用。

出于非语言律师的目的,是的。

出于语言律师的目的,我看不出 uint8_t 可以保证算术运算,但可以保证字符类型(charunsigned charsigned char).

根据 C 2018 7.22.3.4 2 和 3,如果 malloc 不是 return 空指针,则 returned 值指向已分配的 space请求大小的对象。根据 3.15 1,对象是“执行环境中的数据存储区域,其内容可以表示值”。 malloc提供的space是执行环境中的数据存储区域,其内容可以表示值,即使它们还没有。

如果我们将 malloc 的结果赋值给一个指向字符类型的指针,则 6.3.2.3 7 将适用:“……当一个指向对象的指针被转换为一个指向字符类型的指针时,结果指向对象的最低寻址字节。结果的连续递增,直到对象的大小,产生指向对象剩余字节的指针。”虽然没有明确说明,但这被理解为意味着对象可以被视为字符类型的数组,这是 C 标准的其他部分所要求的,例如 6.5 6(“如果一个值被复制到一个没有字符类型的对象中声明类型...作为字符类型的数组,...)。

因此,指针算术运算是针对此对象上 char *unsigned char *signed char * 类型的指针定义的。

uint8_t,如果它由<stdint.h>定义,则必须具有与unsigned char基本相同的属性(两者都是纯二进制,uint8_t不能大于unsigned char 因为 unsigned char 必须支持值 255,并且 uint8_t 不能小于 unsigned char 因为字符类型根据定义是对象大小的基本单位),它不是必须同类型。它可以是 扩展整数类型 ,如 6.2.5 4 所允许的,因此可能不包含在将指针转换为字符类型的规则中。

我认为该标准的相关引用来自第 7.22.3 节,"Memory management functions",第 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).

(强调我的。)

所以malloc返回的内存是一个数组,你这样计算一个指针差是合法的

按照标准:

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.

[C17 § 6.5.6]

否则行为未定义。标准很明确。由于 malloc 返回的值可以分配给指向 "any type of object" 的指针,然后用于访问 "an array of such objects," [C17 § 7.22.3],因此适用上述规则。