C 动态分配和程序

C 动态分配和程序,c,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

我不明白为什么我的代码的第一个版本可以工作,而第二个版本不行

第一版:

#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]);
}
#包括
#包括
无效程序(int*t){
t=(int*)realloc(t,4*sizeof(int));
t[3]=4;
}
int main()
{
int*var;
var=(int*)malloc(sizeof(int));
程序(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]);
}
#包括
#包括
无效程序(int*t){
t=(int*)malloc(4*sizeof(int));
t[3]=4;
}
int main()
{
int*var=NULL;
程序(var);
printf(“%d\n\n”,var[3]);
}

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

如果您想阅读C标准中的功能描述
realloc
,您就会知道

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

因此,在第一种情况下,指针的值没有改变。尽管依赖于此会导致未定义的行为

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

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

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

将main中的
var
设置为NULL。然后将其中的地址(NULL)复制到
过程中的变量
t
。您进入
malloc
内存,并将该地址分配给
t
。但是
t
只是
var
的一个副本,对
t
的任何更改都不会反映在
var
中。在
过程
之外,指针保留空地址,使用
var[3]
调用
printf
是未定义的行为

第二个病例的症状相同,但有扭转
realloc
不必返回其他地址。它是内存分配器感知的,所以如果它能够“扩展”所指向的内存块,它就会。这就是你所看到的。调用
realloc
扩展内存并返回给定的相同地址。因此,完全巧合的是,
t
var
最终仍然指向同一个位置


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

让我们在这里一步一步来

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

在代码的第二个版本中,您只需将地址
var
指向。在
过程(…)
中,本质上您已经声明了一个int指针,并且在第一行(malloc行)上,您正在为该指针赋值<代码>var
不会使用此值更新,因为var是一个完全独立的实体

从本质上讲,您最好执行以下操作:

int *var = NULL;
int *t = malloc(4*sizeof(int));
t[3]=4;
printf("%d\n\n", var[3]);
var
从未重新分配给任何对象,因此var将始终为null

但这是可以纠正的,就像这样:

#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]);
}
#包括
#包括
无效程序(int**t){
*t=malloc(4*sizeof(int));
(*t)[3]=4;
}
int main()
{
int*var=NULL;
程序(var);
printf(“%d\n\n”,var[3]);
}
您可以在以下位置查看此工作:


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

对于@EdHeal可能的重复项,
realloc
malloc
不需要强制转换为什么?练习的目的是使用malloc@DocMogrog-尽管如此,您仍然不需要对两个函数的结果进行强制转换。@EdHeal,啊,谢谢您指出这一点。我复制了OP的代码,忘了更改:P