【问题标题】:Manipulating dynamic array using realloc in a function在函数中使用 realloc 操作动态数组
【发布时间】:2012-12-06 18:03:17
【问题描述】:

使用我在这里学到的知识:How to use realloc in a function in C,我编写了这个程序。

int data_length; // Keeps track of length of the dynamic array.
int n; // Keeps track of the number of elements in dynamic array.

void add(int x, int data[], int** test)
{

    n++;

    if (n > data_length)
    {
        data_length++;
        *test = realloc(*test, data_length * sizeof (int));
    }

    data[n-1] = x;

}

int main(void)
{

    int *data = malloc(2 * sizeof *data);

    data_length = 2; // Set the initial values.
    n = 0;

    add(0,data,&data);
    add(1,data,&data);
    add(2,data,&data);

    return 0;
}

该程序的目标是拥有一个动态数组data,我可以继续向其中添加值。当我尝试向data添加一个值时,如果它已满,则使用realloc增加数组的长度。

问题

这个程序编译,运行时不会崩溃。但是,打印出data[0],data[1],data[2] 会得到0,1,0。数字2 未添加到数组中。

这是因为我错误地使用了realloc吗?

其他信息

这个程序稍后将与不同数量的“添加”和可能的“删除”功能一起使用。另外,我知道 realloc 应该检查它是否失败(是 NULL),但为了简单起见,这里省略了。

我仍在学习和尝试 C。感谢您的耐心等待。

【问题讨论】:

  • 提示:作为形参,int data[]int *data完全相同

标签: c arrays malloc


【解决方案1】:

您的问题在于您对data 的使用,因为它指向旧数组的地址。然后,当您致电realloc 时,该区域将被释放。因此,您正试图在下一条指令中访问无效地址:这会导致未定义的行为。

您也不需要使用这个data 指针。 test 就足够了。

(*test)[n-1] = x;

【讨论】:

    【解决方案2】:

    您无需将data 两次传递给add

    你可以编码

    void add(int x, int** ptr)
    {
      n++;
      int *data = *ptr;
      if (n > data_length) {
        data_length++;
        *ptr = data = realloc(oldata, data_length * sizeof (int));
        if (!data) 
          perror("realloc failed), exit(EXIT_FAILURE);
      }
      data [n-1] = x;
    }
    

    但那是非常低效的,您应该只偶尔致电realloc。例如,您可以拥有

         data_length = 3*data_length/2 + 5;
         *ptr = data = realloc(oldata, data_length * sizeof (int));
    

    【讨论】:

    • 感谢您的意见。尤其是效率低下。 +1
    【解决方案3】:

    我们来看看POSIX realloc specification

    描述说:

    如果内存对象的新大小需要移动对象,则释放对象先前实例化的空间。

    返回值(强调添加)提到:

    在大小不等于 0 的情况下成功完成后,realloc() 返回一个指向(可能已移动)分配空间的指针。

    您可以检查指针是否发生变化。

    int *old;
    old = *test;
    *test = realloc(*test, data_length * sizeof(int));
    if (*test != old)
        printf("Pointer changed from %p to %p\n", old, *test);
    

    这种可能的更改可能会产生不良影响,因为您的代码通过两个不同的名称引用“相同”内存,data*test。如果*test 发生变化,data 仍然指向旧的内存块。

    【讨论】:

    • 感谢您的解释。 +1
    猜你喜欢
    • 2015-02-13
    • 1970-01-01
    • 2020-11-20
    • 2013-02-11
    • 2019-05-23
    • 2021-04-07
    • 1970-01-01
    • 1970-01-01
    • 2020-09-27
    相关资源
    最近更新 更多