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
可以保证算术运算,但可以保证字符类型(char
、unsigned char
或 signed 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],因此适用上述规则。
我正在阅读 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
可以保证算术运算,但可以保证字符类型(char
、unsigned char
或 signed 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],因此适用上述规则。