我不明白为什么我的代码的第一个版本正常运行而第二个版本没有。
第一版:
#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指针。为什么?
答案 0 :(得分:1)
你应该记住,C中的所有都是通过值传递的,甚至是指针。让我们从第二个例子开始。
您将main中的var
设置为NULL。然后将其中的地址(NULL)复制到t
中的可变procedure
。您继续malloc
内存并将该地址分配给t
。但t
只是var
的副本,t
的任何更改都不会反映在var
中。在procedure
之外,指针保留NULL地址,并且printf
对var[3]
的调用是未定义的行为。
第二种情况具有相同的症状,但有一个扭曲。 realloc
不必返回其他地址。它是内存分配器可识别的,所以如果它只是“扩展”指向的内存块,它就会。这就是你所看到的。对realloc
的调用扩展了内存并返回给定的相同地址。因此,仅仅巧合,t
和var
最终仍指向同一位置。
这就是为什么使用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
的值发生了变化。 (因为t
是var
)