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

int a[5], *p = a+5, diff = p-a; // Well-defined

然而,以下是瑞银:

p = a+6;
int b = *(a+5), diff = p-a; // Dereferencing and pointer arithmetic

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

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?

推荐答案

使用指向One-Past-malloc的指针是否定义良好?

如果p指向分配的内存之后的一个,并且它没有被取消引用,这是很好地定义的.

n1570-§6.5.6(P8):

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

减go 两个指针仅当它们指向同一数组对象的元素或指向数组对象的最后一个元素之后的一个元素时才有效,否则将导致未定义的行为.

(p9):

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

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

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

comment中的Jonathan Leffler所示,这对于动态分配的存储器有效的另一个原因是:

§7.22.3 (p1):

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

上述代码片段中由malloc返回的指针被分配给d,分配的内存是一个由5int个对象组成的array.

C++相关问答推荐

不同到达时间的轮询实现

va_copy的使用是未定义的行为吗?

我无法让LLDB正确运行我的可执行文件

Clang:如何强制运行时错误的崩溃/异常由于-fsanitize=undefined

我在这里正确地解释了C操作顺序吗?

将 struct 传递给函数

如何在CANbus RX/TX FIFO起始地址寄存器(ATSAME 51)的特定地址初始化数组?

getline()从c中的外部函数传递指针时输出null

C中的FREE函数正在触发断点

在C++中父进程和子进程中的TAILQ队列同步问题

关于scanf()和空格的问题

错误...的多个定义(&Q)首先在这里定义&

我应该在递归中使用全局变量吗

在运行时判断C/C++指针是否指向只读内存(在Linux操作系统中)

即使我在C++中空闲,也肯定会丢失内存

赋值两侧的后置增量,字符指针

与指针的原始C数组或C++向量<;向量<;双>>;

如何找出C中分配在堆上的数组的大小?

全局变量 y0 与 mathlib 冲突,无法编译最小的 C 代码

段错误try 访问静态字符串,但仅有时取决于构建环境