繁体   English   中英

C - 如何为每个数组元素动态分配内存?

[英]C - How to dynamically allocate memory for each array element?

我有以下结构

typedef struct h{
        int key;
        float data;
        char name[20];
}heaparr;

我想为每个元素动态分配内存

heaparr *heap;

为了动态地为每个元素分配内存,我已经使用过

heap[i]=(heaparr*)malloc(sizeof(heaparr));

但每次编译代码时,都会出现赋值类型不匹配错误。 我该如何解决这个问题? 提前致谢。

您只能通过指针动态分配。 如果要动态分配数组的每个元素,则每个元素必须是指针。

[编辑]感谢@David C. Rankin 指出我在这个特定的例子中我在堆栈中声明了一个包含10个指针的数组,以使代码更简单。 您可以使用任意数量的元素创建预定义大小的数组,但它具有一个限制,即一旦达到限制就无法重新realloc堆数据。 您始终可以动态创建数组。

#include <stdlib.h>

typedef struct h {
    int key;
    float data;
    char name[20];
} heaparr;

int main()
{
    heaparr *heap[10];
    int i;
    for (i = 0; i < 10; ++i) {
        heap[0] = malloc(sizeof(heaparr));
    }

    return 0;
}

作为TheCrow答案的后续内容,如果您确实希望以允许处理和未知数量的结构的方式为每个heap[i]分配,那么您可以使用指向 heaparr 的指针 (例如, heaparr **heap; )然后最初分配一些指针并为每个结构分配,因为它是从输入中读取的。

该计划是直截了当的。 你保留两个计数器变量。 一个表示分配的指针数,第二个表示使用的数字。 当使用指针的数目等于分配数量,您只需realloc试图分配/填充你的下一个指针之前,更多的指针。

以下是从stdin读取数据并希望每行包含"key data name"的简单示例。 最初分配了2指针,并且根据需要通过将当前分配的所有指针都已填充时分配的当前数量加倍来重新分配指针数,例如

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

/* if you need constants, #define them or use a global enum */
enum { NPTR = 2, MAXNM = 20, MAXC = 128 };

typedef struct {
    int key;
    float data;
    char name[MAXNM];
} heaparr;

int main (void) {

    char buf[MAXC] = "";    /* read buffer */
    size_t  n = 0,          /* current struct filled */
            nptr = NPTR;    /* initial/current number of pointers */
    heaparr **heap = NULL;  /* pointer-to-pointer to heaparr */

    /* allocate/validate nptr to heap */
    if (!(heap = malloc (nptr * sizeof *heap))) {
        perror ("malloc-heap");
        return 1;
    }

    while (fgets (buf, MAXC, stdin)) {          /* read each line */
        heaparr tmp = { .key = 0 };             /* tmp struct */
        if (sscanf (buf, "%d %f %19[^'\n']",    /* parse line/validate */
                    &tmp.key, &tmp.data, tmp.name) != 3) {
            fprintf (stderr, "error: failed conversion line %zu.\n", n);
            continue;       /* just read next line on conversion failure */
        }
        if (n == nptr) {    /* check if realloc needed */
            /* always relloc to a temporary pointer to avoid mem-leak */
            void *tmpheap = realloc (heap, nptr * 2 * sizeof *heap);
            if (!tmpheap) { /* validate realloc */
                perror ("realloc-tmpheap");
                break;  /* don't exit, original data still valid in heap */
            }
            heap = tmpheap; /* assign new block to heap */
            nptr *= 2;      /* update current pointers allocated */
        }
        if (!(heap[n] = malloc (sizeof *heap[n]))) { /* allocate heap[n] */
            perror ("malloc-heap[n]");
            break;
        }
        *heap[n++] = tmp;   /* assign tmp to heap[n], increment n */
    }

    for (size_t i = 0; i < n; i++) {    /* output all values */
        printf ("%3d %5.1f   %s\n", heap[i]->key, heap[i]->data, 
                                    heap[i]->name);
        free (heap[i]);     /* don't forget to free each struct */
    }
    free (heap);            /* don't forget to free pointers */

    return 0;
}

(4个结构的数据如下所示,需要上面的realloc

示例输入文件

$ cat dat/intfloatstr.txt
1 1.1 my
2 2.2 dog
3 3.3 has
4 4.4 fleas

示例使用/输出

$ ./bin/dynallocstruct <dat/intfloatstr.txt
  1   1.1   my
  2   2.2   dog
  3   3.3   has
  4   4.4   fleas

内存使用/错误检查

在您编写的任何动态分配内存的代码中,您对分配的任何内存块都有2个职责 :(1) 始终保留指向内存块起始地址的指针,因此,(2)当它为no时可以释放它需要更久。

您必须使用内存错误检查程序,以确保您不会尝试访问内存或写入超出/超出已分配块的范围,尝试读取或基于未初始化值的条件跳转,最后,确认你释放了你分配的所有内存。

对于Linux, valgrind是正常的选择。 每个平台都有类似的记忆检查器。 它们都很简单易用,只需通过它运行程序即可。

$ valgrind ./bin/dynallocstruct <dat/intfloatstr.txt
==8846== Memcheck, a memory error detector
==8846== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==8846== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==8846== Command: ./bin/dynallocstruct
==8846==
  1   1.1   my
  2   2.2   dog
  3   3.3   has
  4   4.4   fleas
==8846==
==8846== HEAP SUMMARY:
==8846==     in use at exit: 0 bytes in 0 blocks
==8846==   total heap usage: 6 allocs, 6 frees, 160 bytes allocated
==8846==
==8846== All heap blocks were freed -- no leaks are possible
==8846==
==8846== For counts of detected and suppressed errors, rerun with: -v
==8846== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

始终确认已释放已分配的所有内存并且没有内存错误。

您可以在指针的帮助下通过获取下标的大小为每个数组索引分配内存,并启动一个所需数组索引大小的循环。

也不需要对malloc的返回进行类型转换。 找到如下所述的代码段:

typedef struct h
{    
 int key;
 float data;
 char name[20];
}heaparr;

int main()
{
  int     size = 4;
  int     iLoop = 0;
  heaparr *heap[size];

  for (iLoop = 0; iLoop < size; iLoop++)
  {
    heap[iLoop] = malloc(sizeof(heaparr));
  } 
return 0;
}

希望这会清除你的怀疑。

我认为下面的代码是适合你的...

int main
{
    ///In Main Function you need to allocate the memory for structure format  
     heaparr *heap;
     int num,i; //How many structures you want it?
     printf("Enter the size");
     scanf("%d",&num);
     heap=malloc(num*sizeof(struct heaparr));
     for(i=0;i<num;i++)
       scanf("%d %f %s",&heap[i].key,&heap[i].data,heap[i].name);//access members and store data
    for(i=0;i<num;i++)
       printf("%d %f %s",heap[i].key,heap[i].data,heap[i].name);//print the data

return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM