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;
}
我认为下面的代码适合您...
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;
}
作为 TheCrow 回答的后续,如果您确实想以允许您处理和未知数量的结构的方式为每个 heap[i]
分配,那么您可以使用 pointer-to-pointer to heaparr
(e.g. heaparr **heap;
) 然后最初分配一些指针,并在从输入读取时为每个结构分配。
方案很简单。您保留两个计数器变量。一个代表分配的指针数量,第二个代表使用的数量。当使用的指针数量等于分配的数量时,您只需 realloc
更多指针,然后再尝试 allocate/fill 下一个指针。
下面是一个从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
示例Use/Output
$ ./bin/dynallocstruct <dat/intfloatstr.txt
1 1.1 my
2 2.2 dog
3 3.3 has
4 4.4 fleas
内存Use/Error检查
在您编写的任何动态分配内存的代码中,您对分配的任何内存块负有 2 责任:(1) 始终保留指向内存块的起始地址 因此,(2) 当不再需要它时可以释放。
您必须使用内存错误检查程序来确保您不会尝试访问内存或写入 beyond/outside 您分配的块的边界,尝试读取或基于未初始化的条件跳转值,最后,确认您释放了所有已分配的内存。
对于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 的 return。
找到下面提到的代码片段:
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;
}
希望这会消除您的疑虑。
我有以下结构
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;
}
我认为下面的代码适合您...
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;
}
作为 TheCrow 回答的后续,如果您确实想以允许您处理和未知数量的结构的方式为每个 heap[i]
分配,那么您可以使用 pointer-to-pointer to heaparr
(e.g. heaparr **heap;
) 然后最初分配一些指针,并在从输入读取时为每个结构分配。
方案很简单。您保留两个计数器变量。一个代表分配的指针数量,第二个代表使用的数量。当使用的指针数量等于分配的数量时,您只需 realloc
更多指针,然后再尝试 allocate/fill 下一个指针。
下面是一个从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
示例Use/Output
$ ./bin/dynallocstruct <dat/intfloatstr.txt
1 1.1 my
2 2.2 dog
3 3.3 has
4 4.4 fleas
内存Use/Error检查
在您编写的任何动态分配内存的代码中,您对分配的任何内存块负有 2 责任:(1) 始终保留指向内存块的起始地址 因此,(2) 当不再需要它时可以释放。
您必须使用内存错误检查程序来确保您不会尝试访问内存或写入 beyond/outside 您分配的块的边界,尝试读取或基于未初始化的条件跳转值,最后,确认您释放了所有已分配的内存。
对于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 的 return。 找到下面提到的代码片段:
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;
}
希望这会消除您的疑虑。