【问题标题】:Using realloc() in dynamic array implementation在动态数组实现中使用 realloc()
【发布时间】:2011-10-06 02:23:10
【问题描述】:

我正在尝试使用 realloc() 在 C 中实现动态数组。我的理解是 realloc() 保留了旧指针指向的内存块的旧内容,但我的以下测试代码另有说明:

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

int DARRAYSIZE=5;

typedef struct dynamicArray{
    int size;
    int *items;
}DArray;

int init(DArray *DAP){ //initialise the DArray
    DAP->items=(int *)malloc(sizeof(int)*DARRAYSIZE);
    if(DAP->items){
        DAP->size=0;
        return 0;
    }else{
        printf("Malloc failed!\n");
        return 1;
    }
}

void print(DArray *DAP){ //print all elements in the DArray
    int i=0;

    for(;i<DAP->size;i++)
        printf("%d\t",DAP->items[i]);

    printf("\n");
}

void add(DArray *DAP,int val){ //add the new val into the DArray
    if(!full(DAP)){
        DAP->items[DAP->size++]=val;    
    }else{
        if(!grow(DAP)){
            DAP->items[DAP->size++]=val;    
        }else
            exit(1);
    }
}

int full(DArray *DAP){ //returns 1 if the DAarray is full
    if(DAP->size==DARRAYSIZE)
        return 1;
    else
        return 0;
}

int grow(DArray *DAP){ //grows the DArray to double its original size
    int *temp=(int *)realloc(DAP->items,DARRAYSIZE*2);
    if(!temp){
        printf("Realloc failed!\n");
        return 1;
    }else{
        DAP->items=temp;
        DARRAYSIZE*=2;
        printf("Darray doubled and current contents are:\n");
        print(DAP);
        return 0;
    }
}

void destroy(DArray *DAP){ //destroies the DArray
    free(DAP->items);
}

int main(void){
    DArray newDA;
    if(!init(&newDA)){
        int i;
        for(i=1;i<30;i++)
            add(&newDA,i);

    }else
        exit(1);

    destroy(&newDA);

    return 0;
}

我所做的是在函数grow() 中将数组的大小加倍后立即打印数组的内容。我使用以下代码编译了代码:

:gcc -版本 i686-apple-darwin11-llvm-gcc-4.2

下面是输出:

输出中有意外的 0。

请指教我在这里做错了什么,谢谢!

【问题讨论】:

  • 发布代码或输入/输出时,最好复制/粘贴文本而不是屏幕截图。
  • 需要将DARRAYSIZE中的信息合并到结构中;你不能让一个全局变量错误控制DArray 类型的所有变量。每个动态数组的大小相互独立。
  • @Jonathan,感谢您的建议,我的代码中确实需要更好的封装。

标签: c memory-management


【解决方案1】:

你在realloc() 中忘记了sizeof(int),所以你一直在缩小你的数组。

您还需要跟踪正在使用的项目数和动态数组结构中分配的空间量;这是两个单独的措施,两者都是必要的。但是您不能使用全局变量(当前为 DYNARRAYSIZE)来保存每个动态数组的大小。每个动态数组需要一个。

还需要看full();它会将大小与 DARRAYSIZE 进行比较...总是!


工作输出

使用设置为 3 的制表位格式化

Darray doubled and current contents are:
Max = 10; Cur = 5
1  2  3  4  5
Darray doubled and current contents are:
Max = 20; Cur = 10
1  2  3  4  5  6  7  8  9  10
Darray doubled and current contents are:
Max = 40; Cur = 20
1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20

工作代码

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

enum { DARRAYSIZE = 5 };

typedef struct dynamicArray
{
    int max_size;
    int cur_size;
    int *items;
} DArray;

extern int  init(DArray *DAP);
extern void add(DArray *DAP, int val);
extern void destroy(DArray *DAP);
extern void print(DArray *DAP);
static int  full(DArray *DAP);
static int  grow(DArray *DAP);

//initialise the DArray
int init(DArray *DAP)
{
    DAP->items=(int *)malloc(sizeof(int)*DARRAYSIZE);
    if (DAP->items)
    {
        DAP->max_size = DARRAYSIZE;
        DAP->cur_size = 0;
        return 0;
    }
    else
    {
        printf("Malloc failed!\n");
        return 1;
    }
}

//print all elements in the DArray
void print(DArray *DAP)
{
    printf("Max = %d; Cur = %d\n", DAP->max_size, DAP->cur_size);
    for (int i = 0; i < DAP->cur_size; i++)
        printf("%d\t", DAP->items[i]);
    printf("\n");
}

//add the new val into the DArray
void add(DArray *DAP, int val)
{
    if (!full(DAP))
        DAP->items[DAP->cur_size++] = val;    
    else if (!grow(DAP))
        DAP->items[DAP->cur_size++] = val;    
    else
        exit(1);
}

//returns 1 if the DAarray is full
static int full(DArray *DAP)
{
    assert(DAP->cur_size >= 0 && DAP->max_size >= 0);
    assert(DAP->cur_size <= DAP->max_size);
    if (DAP->cur_size == DAP->max_size)
        return 1;
    else
        return 0;
}

//grows the DArray to double its original size
static int grow(DArray *DAP)
{
    int *temp=(int *)realloc(DAP->items, sizeof(*temp) * DAP->max_size * 2);
    if (!temp)
    {
        printf("Realloc failed!\n");
        return 1;
    }
    else
    {
        DAP->items = temp;
        DAP->max_size *= 2;
        printf("Darray doubled and current contents are:\n");
        print(DAP);
        return 0;
    }
}

//destroys the DArray
void destroy(DArray *DAP)
{
    free(DAP->items);
    DAP->items = 0;
    DAP->max_size = 0;
    DAP->cur_size = 0;
}

int main(void)
{
    DArray newDA;
    if (!init(&newDA))
    {
        for (int i = 1; i < 30; i++)
            add(&newDA, i);
    }
    else
        exit(1);

    destroy(&newDA);

    return 0;
}

【讨论】:

  • 感谢您的反馈。但是我认为问题不在于 full(),因为我每次都会在 grow() 中将全局变量 DARRAYSIZE 加倍。
  • @Moses:这正是乔纳森所说的。您在full 检查中使用 DARRAYSIZE 的方式表明它应该表示元素的数量。但是,您后者将 DARRAYSIZE 传递给 realloc 但它需要 bytes 的数量,因此会出现错误。
  • @Jonathan: 非常感谢您发现错误和完善的代码 :)
猜你喜欢
  • 2015-02-13
  • 2013-02-11
  • 1970-01-01
  • 2021-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-27
  • 2012-09-28
相关资源
最近更新 更多