动态分配和程序

时间:2017-01-19 20:50:40

标签: c

我不明白为什么我的代码的第一个版本正常运行而第二个版本没有。

第一版:

#include <stdio.h>
#include <stdlib.h>

void procedure(int *t){
    t = (int*)realloc(t, 4*sizeof(int));

    t[3] = 4;
}


int main()
{
    int *var;
    var = (int*)malloc(sizeof(int));

    procedure(var);

    printf("%d\n\n", var[3]);
}

第二版:

#include <stdio.h>
#include <stdlib.h>

void procedure(int *t){
    t = (int*)malloc(4*sizeof(int));

    t[3] = 4;
}


int main()
{
    int *var = NULL;


    procedure(var);

    printf("%d\n\n", var[3]);
}

在第二个版本中,var在执行过程后仍然是一个NULL指针。为什么?

4 个答案:

答案 0 :(得分:1)

你应该记住,C中的所有都是通过值传递的,甚至是指针。让我们从第二个例子开始。

您将main中的var设置为NULL。然后将其中的地址(NULL)复制到t中的可变procedure。您继续malloc内存并将该地址分配给t。但t只是var的副本,t的任何更改都不会反映在var中。在procedure之外,指针保留NULL地址,并且printfvar[3]的调用是未定义的行为。

第二种情况具有相同的症状,但有一个扭曲。 realloc不必返回其他地址。它是内存分配器可识别的,所以如果它只是“扩展”指向的内存块,它就会。这就是你所看到的。对realloc的调用扩展了内存并返回给定的相同地址。因此,仅仅巧合,tvar最终仍指向同一位置。

这就是为什么使用t[3]可以看到对var[3]的修改。这不是您可以依赖的行为。

答案 1 :(得分:1)

在代码的第二个版本中,您只需将地址var传递给。在procedure(...)中,你实际上已经声明了一个int-pointer并且在第一行( malloc line ),你正在为该指针赋值。 var未使用此值进行更新,因为var完全是一个单独的实体。

基本上,你可能会做以下事情:

int *var = NULL;
int *t = malloc(4*sizeof(int));
t[3]=4;
printf("%d\n\n", var[3]);

var永远不会被重新分配给任何东西,所以var总是为空。

这可以纠正,但是,如下:

#include <stdio.h>
#include <stdlib.h>

void procedure(int **t){
    *t = malloc(4*sizeof(int));

    (*t)[3] = 4;
}


int main()
{
    int *var = NULL;

    procedure(&var);

    printf("%d\n\n", var[3]);
}

您可以在以下位置查看此工作:https://ideone.com/aTY9Ok

编辑:另外,值得注意的是,您应该在第一个版本中执行相同操作,因为realloc(...)可能会返回与var不同的地址内存泄漏。

答案 2 :(得分:0)

如果要阅读C标准中函数realloc的描述,那么您将知道

  

返回4   realloc函数返回指向新对象的指针   (可能与指向旧对象的指针具有相同的值),或   如果无法分配新对象,则为空指针。

所以在第一种情况下,它发生了这样一种方式,指针的值没有改变。虽然依靠这会导致未定义的行为。

在第二种情况下,当使用标准函数malloc时,分配了具有不同地址的新范围。因此原始指针不指向新的内存范围,因为它是按值传递给函数的。

因此,在这两种情况下,原始指针都没有改变。不同之处在于,在第一种情况下,系统只能扩大内存范围,保持其原始地址不变,而在第二种情况下,系统会分配一个具有不同地址的新范围。

答案 3 :(得分:0)

让我们一步一步来看。

  • int *t表示“t的地址”,表示它只是一个数字
  • 将任何数字传递给函数意味着您将数据复制到该函数中(不是链接它)
  • 这意味着数字可以在函数内部更改,但不能在外部(因为它是副本)
  • 即使t是一个指针,该指针仍然是一个数字......设置等于其他东西(即t = (int*)malloc(4*sizeof(int));)并不意味着var的值发生了变化。 (因为tvar
  • 的副本