重新分配参数
Realloc Arguments
我正在使用带有以下代码的数组实现 Stack
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct Stack{
int top;
int capacity;
int *array;
};
struct Stack *createStack()
{
struct Stack *stack=malloc(sizeof(struct Stack));
stack->top=-1;
stack->capacity=1;
stack->array=malloc(sizeof(sizeof(int)*stack->capacity));
}
void doubleStack(struct Stack *stack)
{
stack->capacity=stack->capacity*2;
stack->array=realloc(stack,stack->capacity);
}
void push( struct Stack *stack , int data)
{
if(stack->top==(stack->capacity)-1)
doubleStack(stack);
stack->array[++stack->top]=data;
}
我的疑问是,一旦堆栈已满,调用 doubleStack
时,
我应该使用 stack->array
作为 realloc()
的第一个参数还是 stack
作为 realloc()
的第一个参数?
嗯,我认为 stack->array
应该通过。因为我们只需要重新分配那部分内存。
但不小心我通过了 stack
,这似乎也有效。请指教。
如您所想,
stack->array=realloc(stack,stack->capacity);
至少应该是
stack->array=realloc(stack->array,stack->capacity);
否则,如果成功,您将 free()
-ing up stack
本身,然后您将最终访问它。这会调用 undefined behaviour。获得 UB 后,许多事情 "seem" 都可以使用。
也就是说,从使用的角度来说,
p = realloc(p, q);
这种代码很糟糕,好像realloc()
失败了,它不会修改作为参数传递的p
,但是由于[=的直接赋值realloc()
的 40=] 值变为 p
,p
将被设置为 NULL
,丢失实际存储的指针。
提示:始终使用临时指针收集 realloc()
的 return 值,然后检查 realloc()
是否成功,如果成功,分配新的 returned 指向已传递给 realloc()
.
的指针
您应该向 realloc
传递一个指向您希望扩展的数组的指针。由于 stack
不是您希望扩展的数组,而 stack->array
是,您应该将 stack->array
作为第一个参数传递。
但是,您应该将 realloc
的结果存储在一个单独的变量中并进行 NULL
检查。
If the function fails to allocate the requested block of memory, a
null pointer is returned, and the memory block pointed to by argument
ptr is not deallocated (it is still valid, and with its contents
unchanged).
否则您可能会造成内存泄漏:
int *tmp = realloc(stack->array, stack->capacity);
if (tmp) {
stack->array = tmp;
} else {
... // Deal with the allocation error here
}
首先函数push
是错误的
void push( struct Stack *stack , int data)
{
if(stack->top==(stack->capacity)-1)
doubleStack(stack);
stack->array[++stack->top]=data;
}
最初top
设置为1,capacity
也设置为1。
所以这个条件
if(stack->top==(stack->capacity)-1)
产生 false
和下面的语句
stack->array[++stack->top]=data;
被执行。它写入超出分配数组的内存 stack->array[2]
。
我认为最初top
应该设置为0。函数应该按以下方式定义
void push( struct Stack *stack , int data )
{
if ( stack->top != stack->capacity || doubleStack( stack ) )
{
stack->array[stack->top++] = data;
}
}
在这种情况下,您可以简单地定义一个报告堆栈是否为空的函数,方法如下
int empty( struct Stack *stack ) { return stack->top == 0; }
至于函数doubleStack
那么应该这样定义
int doubleStack(struct Stack *stack)
{
int success = 0;
int new_capacity = 2 * stack->capacity;
int *tmp = = realloc( stack->array, new_capacity * sizeof( int ) );
if ( ( success = tmp != NULL ) )
{
stack->capacity = new_capacity;
stack->array = tmp;
}
return success
}
考虑到我将函数的 return 类型从 void
更改为 int
。
我还使用了一个中间变量 new_capacity
。如果重新分配失败,当前容量将不会改变
我正在使用带有以下代码的数组实现 Stack
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct Stack{
int top;
int capacity;
int *array;
};
struct Stack *createStack()
{
struct Stack *stack=malloc(sizeof(struct Stack));
stack->top=-1;
stack->capacity=1;
stack->array=malloc(sizeof(sizeof(int)*stack->capacity));
}
void doubleStack(struct Stack *stack)
{
stack->capacity=stack->capacity*2;
stack->array=realloc(stack,stack->capacity);
}
void push( struct Stack *stack , int data)
{
if(stack->top==(stack->capacity)-1)
doubleStack(stack);
stack->array[++stack->top]=data;
}
我的疑问是,一旦堆栈已满,调用 doubleStack
时,
我应该使用 stack->array
作为 realloc()
的第一个参数还是 stack
作为 realloc()
的第一个参数?
嗯,我认为 stack->array
应该通过。因为我们只需要重新分配那部分内存。
但不小心我通过了 stack
,这似乎也有效。请指教。
如您所想,
stack->array=realloc(stack,stack->capacity);
至少应该是
stack->array=realloc(stack->array,stack->capacity);
否则,如果成功,您将 free()
-ing up stack
本身,然后您将最终访问它。这会调用 undefined behaviour。获得 UB 后,许多事情 "seem" 都可以使用。
也就是说,从使用的角度来说,
p = realloc(p, q);
这种代码很糟糕,好像realloc()
失败了,它不会修改作为参数传递的p
,但是由于[=的直接赋值realloc()
的 40=] 值变为 p
,p
将被设置为 NULL
,丢失实际存储的指针。
提示:始终使用临时指针收集 realloc()
的 return 值,然后检查 realloc()
是否成功,如果成功,分配新的 returned 指向已传递给 realloc()
.
您应该向 realloc
传递一个指向您希望扩展的数组的指针。由于 stack
不是您希望扩展的数组,而 stack->array
是,您应该将 stack->array
作为第一个参数传递。
但是,您应该将 realloc
的结果存储在一个单独的变量中并进行 NULL
检查。
If the function fails to allocate the requested block of memory, a null pointer is returned, and the memory block pointed to by argument ptr is not deallocated (it is still valid, and with its contents unchanged).
否则您可能会造成内存泄漏:
int *tmp = realloc(stack->array, stack->capacity);
if (tmp) {
stack->array = tmp;
} else {
... // Deal with the allocation error here
}
首先函数push
是错误的
void push( struct Stack *stack , int data)
{
if(stack->top==(stack->capacity)-1)
doubleStack(stack);
stack->array[++stack->top]=data;
}
最初top
设置为1,capacity
也设置为1。
所以这个条件
if(stack->top==(stack->capacity)-1)
产生 false
和下面的语句
stack->array[++stack->top]=data;
被执行。它写入超出分配数组的内存 stack->array[2]
。
我认为最初top
应该设置为0。函数应该按以下方式定义
void push( struct Stack *stack , int data )
{
if ( stack->top != stack->capacity || doubleStack( stack ) )
{
stack->array[stack->top++] = data;
}
}
在这种情况下,您可以简单地定义一个报告堆栈是否为空的函数,方法如下
int empty( struct Stack *stack ) { return stack->top == 0; }
至于函数doubleStack
那么应该这样定义
int doubleStack(struct Stack *stack)
{
int success = 0;
int new_capacity = 2 * stack->capacity;
int *tmp = = realloc( stack->array, new_capacity * sizeof( int ) );
if ( ( success = tmp != NULL ) )
{
stack->capacity = new_capacity;
stack->array = tmp;
}
return success
}
考虑到我将函数的 return 类型从 void
更改为 int
。
我还使用了一个中间变量 new_capacity
。如果重新分配失败,当前容量将不会改变