malloc和realloc有什么区别?

16

假设我有两个创建10个元素的整数数组的代码示例:

int *pi = (int*)0; 
realloc(pi,10);

另一种是正常书写的方式,即:

int *pi;
pi= malloc(10*sizeof(int));
现在,我的问题是:第一种赋值方式是合法的,但没有使用。为什么,尽管我可能会得到我想要的起始位置?常量初始化指针是合法的,但是为什么没有使用呢?

现在,我的问题是:第一种赋值方式是合法的,但没有被使用。尽管我可以获得我所需的起始位置,为什么还是不用它呢?将指针初始化为常量是合法的,但为什么没有被使用呢?


3
在 C 语言中,你不应该将 malloc 的返回值转换为另一种数据类型。 - RedX
3个回答

30

当传递NULL时,realloc等效于malloc。如果您正在重新分配某种循环中的内存并且不想在第一次分配时拥有特殊情况,则NULL调用可能很有用。


顺便说一下,使用mallocrealloc的相当标准的方法是:

int* p;
p = malloc(10 * sizeof(int)); //Note that there's no cast
//(also, it could just be int* p = malloc(...);)

int* np = realloc(p, 15 * sizeof(int));
//Note that you keep the old pointer -- this is in case the realloc fails
作为一个次要的侧面说明:历史是你看到声明和分配在不同行的主要原因。在早期版本的C语言中,声明必须首先出现在函数中。这意味着即使您的函数直到20行后才使用变量,您也必须在顶部声明。

由于通常不知道在另外20行中没有使用的变量的值应该是什么,因此您不能始终将其初始化为任何有意义的值,因此您在函数顶部只有一个声明而没有分配。

在C99/C11中,您不必在作用域的顶部声明变量。实际上,通常建议在尽可能靠近它们的使用时定义变量。


2
或者 NULL。只要编译器不抛出编译错误,这是合法的。 - Daniel Fischer
3
@me.deeiip 不,那是一个错误的假设。你不能随意使用内存地址,你使用的地址必须由其他函数授予给你,并确保系统知道如何允许你使用它们。 - mah
但在gcc中,使用常量值(带有强制转换)初始化指针正常工作(在Ubuntu 11中)。但在Windows上使用VC ++编译器失败。 - deeiip
1
@me.deeiip 这是因为你已经进入了未定义行为的世界。在未定义行为中可能出现的行为之一是“正确”的行为,但这并不是保证的。 - Corbin
1
@me.deeiip:行为是未定义的;它可能看起来正常工作,但这是偶然而非设计。realloc的第一个参数必须是NULL或者*alloc函数之一的结果。 - John Bode
显示剩余3条评论

11

C要求传递给realloc的指针必须是从malloccallocrealloc函数调用中获得的指针(或空指针)。


calloc 或者之前的 realloc,或许还有其他的? - mah
2
@mah 可能是表达这个意思的 alloc 函数族中最好的方式。 - dmckee --- ex-moderator kitten
1
@dmckee 一个过于谨慎的评论者可能会添加“[从未被释放过]的alloc函数族获得的指针”,但那是多余的:释放任何版本的指针都会使其所有副本不确定。另外的副本在某种意义上已经不存在了,因此不能传递给realloc()free()。http://blog.frama-c.com/index.php?post/2012/01/05/Double-free - Pascal Cuoq
3
::摇摇晃晃地扶着心口,夸张地表演:: 噢,我好倒霉!再次被打败了!*::跌倒在地上,唱着咏叹调,用很长的时间死去::* @PascalCuoq你赢了。 - dmckee --- ex-moderator kitten
非常准确地说,alloca()必须被排除在外,因为它不会从堆中分配内存。 - glglgl

5
第一个任务是不合法的,因为你传递给realloc()的指针必须是先前通过某种方式分配给你的。此外,你忽略了它的返回值,这是你在分配内存时绝不能做的事情! malloc()用于创建固定大小的缓冲区。而realloc()则用于释放一个缓冲区并获取另一个(可能)不同大小的缓冲区,并且它可能会返回你之前使用的相同缓冲区。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接