如何释放 C 中 malloc 数组的最后一个元素?

How to free the final element of a malloc'd array in C?

假设我像这样初始化一个包含 5 个整数元素的数组:

int *Q = malloc(sizeof(int) * 5);

for (int i = 0; i < 5; i++) {
    Q[i] = i;
}

数组如下所示:{0, 1, 2, 3, 4}。 现在,如果我将所有内容移动 1 个位置:

Q++;

数组如下所示:{1, 2, 3, 4, #},其中 # 是一些垃圾值。

有没有办法释放最后一个元素,使其不存储在数组中?

我试过这个:

free(Q[4]);

但我知道这行不通,因为 free() 只能操作分配给 Q 的整个内存块。

有没有更好的方法来改变一切?生成的数组应如下所示:{1, 2, 3, 4}.

每次轮班后重新分配 () Q 是个好主意吗?

realloc() 可以更改分配的内存块的大小,这将为您完成这项工作。请注意,这不能用于 "free" 数组的任意元素,但只能用于末尾的一个。

这样做的好主意取决于许多因素,none 您已经提供了这些因素。

关于数组的最后一个元素,你肯定可以使用 realloc

顺便说一句,请注意当你说

数组如下所示:{1, 2, 3, 4, #},其中 # 是一些垃圾值。

你错了,你正在调用未定义的行为,正如 this SO answer 所解释的那样。

所以左移值的循环不用做Q[4] = Q[5];

当你执行 Q++ 时,数组没有改变,它仍然包含五个值 0、1、2、3、4,只是 Q 指向数组中的第二个元素。

如果您想更改已分配内存的大小,请按照 Scott 所说的那样进行 realloc 块 - 但这是一种处理堆内存的昂贵方法。

如果您只想跟踪数组中元素的数量,让 Q 保持指向第一个元素,并有一个大小变量指示有多少个整数。

或者使用另一种数据结构来保存整数,例如整数链表,然后您可以更轻松地添加和删除整数。

要在数组内移动元素,可以使用 memmove().

#include <stdio.h>
#include <string.h>

int main(void)
{
  int d_init[] = {0, 1, 2, 3, 4};

  size_t s = sizeof d_init/sizeof *d_init;
  int d[s];

  /* Fill d */
  memcpy(d, d_init, s * sizeof *d);

  for (size_t i = 0; i < s; ++i)
    printf("%d ", d[i]);
  puts("\n");

  /* shift one to the left */
  memmove(d, d + 1, (s - 1) * sizeof *d);

  for (size_t i = 0; i < s; ++i)
    printf("%d ", d[i]);
  puts("\n");


  /* shift two to the right */
  memmove(d + 2, d, (s - 2) * sizeof *d);  

  for (size_t i = 0; i < s; ++i)
    printf("%d ", d[i]);
  puts("\n");
}

上面的代码片段将打印:

0 1 2 3 4
1 2 3 4 4
1 2 1 2 3

如果你正在做 Q++ 你没有移动数组的元素,你的数组只是指向第二个元素(索引 1)。因此,Q[4] 正在读取不属于数组的内容:C 允许您这样做(在大多数情况下),但这是一个错误。

要移动元素,您应该这样做

for (int i=0; i<4; i++)
    Q[i] = Q[i+1];

或(更聪明)

memmove(Q, Q+1, 4*sizeof(int));

但实际上,要拥有大小为 4 的数组,您必须重新分配。

但是如果你需要这样做,也许数组不是你应该使用的数据结构:链表似乎是更好的选择。