使用malloc和realloc使用C动态分配

时间:2013-12-26 17:09:52

标签: c realloc

我在C中使用malloc和realloc函数时遇到了一些麻烦,并使用2个单独的函数在其中保存值

注意我最近才开始使用c,并且可能代码中存在多个错误但我主要关注的是将值保存到结构

我需要能够将多个值保存到单个数组中。

这些是我的功能

int ArrayCreate() {

  int *pt;

  pt = (ASet *)calloc(1,sizeof(ASet));
  pt == NULL;

  return *pt;
}

//possible 2nd *
void ArrayAdd(ASet **arrayStruct, int x) {

  ASet *pt = NULL;

  *arrayStruct=realloc(*arrayStruct,1*sizeof(ASet));
  pt = arrayStruct;
  *arrayStruct->value = x;

  free(pt);
}

在我的主要内容中

ASet *arr_pt = NULL;

创建一个数组

 printf("a new array is created \n"); 
 arr_pt = ArrayCreate();        

 break;

向数组添加内容

 printf("Enter integer \n");            
 scanf("%d",&x);

 ArrayAdd(arr_pt,x);

 while (getchar() != '\n') {
   continue;
 }

 break;

也测试我添加了这个,但我不确定

void ArrayShow(ASet *arrayStruct) {

  ASet *pt = arrayStruct;

  //printf("%d \n", pt[0].value);
  printf("%d \n", pt[1].value);
  printf("%d \n", pt[2].value);
  printf("%d \n", pt[3].value);
  printf("%d \n", pt[4].value);
}

我只需要知道如何使用realloc和calloc正确保存,但由于某种原因,pt [0]被忽略,p [1]之后的任何东西都是垃圾

4 个答案:

答案 0 :(得分:1)

简单样本

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

typedef int Item;

#define PRN_Item "%d"

typedef struct da {
    size_t size;
    Item *value;
} ASet;

ASet *ArrayCreate(void){
    return calloc(1, sizeof(ASet));
}

void ArrayAdd(ASet *arrayStruct, Item x){
    ASet *ap = arrayStruct;
    Item *p = ap->value;
    p = realloc(p, (ap->size + 1)*sizeof(Item));
    if(p){
        ap->value = p;
        ap->value[ap->size] = x;
        ap->size += 1;
    } else {
        perror("realloc");
        exit(1);
    }
}

void ArrayShow(ASet *arrayStruct) {
    Item *v = arrayStruct->value;
    size_t n = arrayStruct->size;
    while(n--){
        printf(PRN_Item " \n", *v++);
    }
}

void ArrayDrop(ASet *arrayStruct){
    free(arrayStruct->value);
    free(arrayStruct);
}

int main(){
    ASet *arr_pt = ArrayCreate();

    if(!arr_pt){
        perror("ArrayCreate");
        exit(1);
    }
    printf("a new array is created \n");
    while(1){
        int x;
        printf("Enter integer \n");            
        if(1!=scanf("%d", &x))
            break;
        ArrayAdd(arr_pt, x);
    }
    ArrayShow(arr_pt);
    ArrayDrop(arr_pt);
    return 0;
}

答案 1 :(得分:0)

修改

以下行是注释,因此未执行:

//printf("%d \n", pt[0].value);

你向pt施放错误的类型,这就是为什么你会得到垃圾

/ *用int替换Aset,SIZE必须是定义的大小* /     pt = calloc(SIZE,sizeof(int));

pt == NULL是一个比较表达,而不是一个assmentment statment:

pt = NULL // assining NULL to pt

ArrayCreate必须返回指向数组fisrt元素的指针,而不是指向的地址值:

int *ArrayCreate() {

int *pt;

pt = calloc(SIZE,sizeof(int));
pt == NULL;

return pt;
}

答案 2 :(得分:0)

问题:

  1. 没有关于数组大小的可见记录,因此您无法确定要重新分配的大小。

  2. 您的ArrayCreate()函数应返回指向结构的指针。 pt == NULL;语句什么都不做;你的编译器应该警告你一个没有效果的语句。因为您返回的是int而不是指针,所以您正在泄漏内存。

  3. 您的ArrayAdd()函数不知道要分配多少空间(再次指向1)。代码不应该使用free(pt); realloc()可能已经返回指向同一位置或不同位置的指针,但不管怎样,它都处理了旧内存。


  4.   

    我不明白1,2;所以你说pt应该是*pt?这将产生什么影响?3部分是关于多少空间?

    考虑ArrayCreate()函数 - 正如当前所写:

    int ArrayCreate() {
    
      int *pt;
    
      pt = (ASet *)calloc(1,sizeof(ASet));
      pt == NULL;
    
      return *pt;
    }
    

    首先,代码对于处理int还是ASet类型感到困惑。它似乎是分配一个带有1(归零)ASet元素的数组,但将其分配给int *。下一行应该是if语句。代码应该是:

    ASet *ArrayCreate(void)
    {
        ASet *pt = (ASet *)calloc(1, sizeof(ASet));
        if (pt == NULL)
        {
            fprintf(stderr, "Memory allocation failed!\n");
            exit(1);
        }
        return pt;
    }
    

    我不反对从calloc()返回的演员表,只要你向我保证你总是用选项编译,如果你忘记包含<stdlib.h>,你的代码将无法编译。例如,我主要使用GCC并始终使用以下选项进行编译:

    gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Werror ...
    

    如果你不这样编译,那么你最好省略演员表。正如您将注意到的那样,还有其他人对malloc()等人的回报问题不够灵活。 (我甚至在其他人的代码上使用这些选项;有时很难让他们的代码干净地编译。)

    错误处理或内存分配是关于最简单的可用选项 - 报告错误(标准错误,记录错误)并退出。你可以像你一样有创意地处理错误,但在很多情况下快速失败有很多优点。

    现在,我展示的代码或多或少是连贯的,但是你知道ASet值数组中有一个元素的唯一方法是......因为它只是用一个元素创建的。

    第一次调用ArrayAdd()时,可以假设数组中有一个元素,但是当你再次调用它时,你不知道数组中有多少行,所以你' ll仍然会为数组分配2个元素,即使这是一个无操作。你需要以某种方式知道数组中已有多少元素。

    如目前所述:

    void ArrayAdd(ASet **arrayStruct, int x) {
    
      ASet *pt = NULL;
    
      *arrayStruct=realloc(*arrayStruct,1*sizeof(ASet));
      pt = arrayStruct;
      *arrayStruct->value = x;
    
      free(pt);
    }
    

    您获取传递的(指向)数组,并将数组的大小调整为一个元素。 pt = arrayStruct;行应该生成编译警告;您正在为ASet **分配ASet *;他们是非常不同的类型。 free(pt)完全错了 - 无可救药地错了。你需要类似的代码:

    void ArrayAdd(ASet **arrayStruct, size_t new_size, int x)
    {
        ASet *pt = realloc(*arrayStruct, new_size * sizeof(ASet));
        if (pt == 0)
        {
            fprintf(stderr, "Memory allocation failed!\n");
            exit(1);
        }
        pt[new_size-1].value = x;
        *arrayStruct = pt;
    }
    

    此外,代码在内存分配失败时会快速失败。在它知道这样做是安全的之前,小心不要破坏*arrayStruct。它将x分配给数组最后一个元素的value成员。请注意,realloc()不会将其提供的额外内存归零。代码也不知道数组之前有多大;它无法判断数组是在增长还是在缩小 - 只有调用代码才能知道该信息。

    所以,这不是一个非常好的代码,但它比以前更好。

答案 3 :(得分:0)

您的代码存在一些问题,例如:

  • 而不是pt == NULL;您应该pt = NULL,因为使用ptNULL之间的第一次比较并且不会将NULL分配给pt }
  • pt = arrayStruct是非法的,因为pt的类型为ASetarrayStruct的类型为**ASet,您应将其替换为pt = *arrayStruct < / LI>
  • 此处*arrayStruct->value = x;就像您要求将value成员的地址更改为x而应该*(arrayStruct)->value = x;