使用指向one-past-malloc的指针是否定义明确? [英] Is it well-defined to use a pointer pointing to one-past-malloc?

查看:56
本文介绍了使用指向one-past-malloc的指针是否定义明确?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C语言中,最好使指针指向数组的最后一个元素之后,并在指针算术中使用它,只要不取消引用它即可:

  int a [5],* p = a + 5,diff = p-a;//定义明确 

但是,这些是UB:

  p = a + 6;int b = *(a + 5),diff = p-a;//解引用和指针运算 

现在我有一个问题:这是否适用于动态分配的内存?假设我只使用了指针算术中的倒数第二个指针,而没有取消引用它,并且 malloc()成功.

  int * a = malloc(5 * sizeof(* a));assert(a!= NULL,内存分配失败");//问题:int * p = a + 5;int diff = p-a;//在指针算术中使用? 

解决方案

使用指向one-past-malloc的指针是否定义明确?

如果 p 指向已分配的内存之后的指针并且未取消引用,则定义良好.

n1570 -§6.5.6(p8):

[...]如果结果指向数组对象的最后一个元素之后,则不应将其用作被评估的一元 * 运算符的操作数.

相减两个指针仅在它们指向同一数组对象的元素或指向数组对象最后一个元素的元素之后才有效,否则将导致不确定的行为.

(p9):

减去两个指针时,两个指针都应指向同一数组对象的元素,或者指向数组对象的最后一个元素[...]

以上引号非常适用于动态和静态分配的内存.

  int a [5];ptrdiff_t diff =& a [5]-& a [0];//定义明确int * d = malloc(5 * sizeof(* d));assert(d!= NULL,内存分配失败");diff =& d [5]-& d [0];//定义明确 

Jonathan Leffler 评论是:

§7.22.3(p1):

连续调用 aligned_alloc calloc malloc realloc 功能未指定.如果分配成功,则返回的指针将进行适当的对齐,以便可以将其分配给具有基本对齐要求的任何类型的对象的指针,然后将其用于访问此类对象或此类对象的数组在分配的空间中(直到明确释放该空间为止).

上面代码段中的 malloc 返回的指针被分配给 d ,分配的内存是5个 int 对象的数组./p>

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?

解决方案

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.

这篇关于使用指向one-past-malloc的指针是否定义明确?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆