malloc 块是否允许指针算术?

Jul*_*ius 6 c pointers pointer-arithmetic language-lawyer

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

(6.5.6 加法运算符)

9 当两个指针相减时,两个指针都指向同一个数组对象的元素,或者指向数组对象最后一个元素之后的一个;结果是两个数组元素的下标之差。

现在我想知道什么被认为是“数组对象”。更具体地说,我想知道下面这个愚蠢的例子是否合法?该分配的内存块是否被视为一个“数组对象”?

uint8_t *data = malloc(255);
uint8_t *end = data + 255;
ptrdiff_t size = end - data;
Run Code Online (Sandbox Code Playgroud)

Chr*_*ons 6

我在标准中找不到任何内容充分定义了“数组对象”的构成,但是查看 C11 标准草案 7.22.3 中的内存分配函数,我确实发现了这一点:

通过连续调用aligned_alloccallocmallocrealloc函数分配的存储的顺序和连续性 是未指定的。如果分配成功,则返回的指针会被适当对齐,以便可以将其分配给具有基本对齐要求的任何类型对象的指针,然后用于访问分配的空间中的此类对象或此类对象的数组(直到空间被显式释放)。

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


Eri*_*hil 5

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

\n\n

出于语言律师的目的,我不认为 可以保证算术运算uint8_t,但可以使用字符类型(charunsigned charsigned char)来保证算术运算。

\n\n

根据 C 2018 7.22.3.4 2 和 3,如果malloc不返回空指针,则返回值指向为请求大小的对象分配的空间。根据3.15 1,对象是执行环境中数据存储的\xe2\x80\x9c区域,其内容可以表示值\xe2\x80\x9d。提供的空间malloc是执行环境中的数据存储区域,其内容可以表示值,即使它们还不能表示值。

\n\n

如果我们将 的结果分配malloc给指向字符类型的指针,则 6.3.2.3 7 将适用: \xe2\x80\x9c\xe2\x80\xa6 当指向对象的指针转换为指向字符类型的指针时, result 指向对象的最低寻址字节。结果的连续增量,直到对象的大小,产生指向对象的剩余字节的指针。\xe2\x80\x9d 尽管没有明确说明,但这被理解为意味着该对象可以被视为字符数组类型,这是 C 标准的其他部分所要求的,例如 6.5 6 (\xe2\x80\x9c如果将值复制到没有声明类型 \xe2\x80\xa6 的对象中作为字符类型数组,\ xe2\x80\xa6)。

\n\n

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

\n\n

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

\n