【问题标题】:How to free the final element of a malloc'd array in C?如何在 C 中释放 malloc 数组的最后一个元素?
【发布时间】:2016-05-25 12:33:08
【问题描述】:

假设我初始化一个包含 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 会是个好主意吗?

【问题讨论】:

  • 是的,如果你这样做Q++,那么调整size--。你有一大块内存,你可以控制你如何访问它。
  • Q++ 之后,Q[4] 不包含“垃圾”。访问它是未定义
  • 你可以使用realloc
  • 如果它只是一个元素,它是否值得工作是值得怀疑的,你很可能不会通过这样做在现实中释放任何内存。
  • 您可能应该提供更多上下文。这听起来像是一个 XY 问题 (meta.stackexchange.com/questions/66377/what-is-the-xy-problem),您真正想做什么?

标签: c arrays malloc free


【解决方案1】:

realloc() 可以更改分配的内存块的大小,这将为您完成这项工作。请注意,这不能用于“释放”数组的任意元素,而只能用于“释放”最后一个。

这样做的好坏取决于许多因素,您都没有提供。

【讨论】:

    【解决方案2】:

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

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

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

    或者使用另一种数据结构来保存您的整数,例如一个整数的链表,那么你可以更容易地添加和删除整数。

    【讨论】:

      【解决方案3】:

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

      顺便说一句,当你说的时候请注意

      数组看起来像:{1, 2, 3, 4, #},其中 # 是一些垃圾值。

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

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

      【讨论】:

        【解决方案4】:

        要在数组中移动元素,可以使用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");
        }
        

        上面的 sn-p 会打印:

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

        【讨论】:

          【解决方案5】:

          如果您正在执行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 的数组,您必须重新分配。

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-10-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多