您尝试使用指针表示法而不是使用数组索引表示法让事情变得更加困难。例如,您分配的students 很好,但请参阅Do I cast the result of malloc?。
当您开始使用学生时,虽然 (students + i)->roll_no = i + 1; 在技术上还不错,但它的可读性更高:students[i].roll_no = i + 1;。 [..] 也可以作为取消引用。您对每个学生 ptr_mark 的分配将是:
students[i].ptr_marks = malloc (sizeof(int) * marks);
assert (students[i].ptr_marks);
(注意:验证每个分配)
其余部分只是清理工作,并与在 students[]... 上使用数组索引概念保持一致,并确保您验证每个输入,例如
for (int j = 0 ; j < marks ; j++) {
printf ("Enter Mark for Subject %d: ", j+1);
if (scanf ("%d", &students[i].ptr_marks[j]) != 1)
return 1;
}
然后您可以通过以下方式释放所有已分配的内存块:
for (int i = 0; i < num_students; i++)
free (students[i].ptr_marks); /* free storage for ptr_marks */
free(students); /* free pointers */
总而言之,你可以这样做:
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#define debugging
struct Student {
int age;
int roll_no;
int* ptr_marks;
};
int main (void) {
// total number of students
int num_students;
printf("Enter # of Students: ");
if (scanf("%d",&num_students) != 1)
return 1;
// structure array definition
struct Student *students;
students = malloc (num_students * sizeof(struct Student));
assert(students != NULL);
int marks;
for (int i = 0 ; i < num_students ; i ++) {
students[i].roll_no = i + 1;
students[i].age = i + 10;
printf("Enter #'s of Subjects for Student %d: ",i);
if (scanf("%d", &marks) != 1)
return 1;
// allocating memory for marks obtained by each student
students[i].ptr_marks = malloc (sizeof(int) * marks);
assert (students[i].ptr_marks);
for (int j = 0 ; j < marks ; j++) {
printf ("Enter Mark for Subject %d: ", j+1);
if (scanf ("%d", &students[i].ptr_marks[j]) != 1)
return 1;
}
}
#ifdef debugging
for (int j = 0 ; j < num_students ; j ++) {
printf("The roll # of student %d are %d \n", j+1, (students+j)->roll_no);
}
#endif
for (int i = 0; i < num_students; i++)
free (students[i].ptr_marks);
free(students);
return 0;
}
使用/输出示例
使用其他输入进行锻炼会导致:
$ ./bin/struct_ptr_alloc
Enter # of Students: 2
Enter #'s of Subjects for Student 0: 3
Enter Mark for Subject 1: 90
Enter Mark for Subject 2: 91
Enter Mark for Subject 3: 94
Enter #'s of Subjects for Student 1: 3
Enter Mark for Subject 1: 87
Enter Mark for Subject 2: 72
Enter Mark for Subject 3: 93
The roll # of student 1 are 1
The roll # of student 2 are 2
内存使用/错误检查
在您编写的任何动态分配内存的代码中,对于分配的任何内存块,您都有 2 个职责:(1)始终保留指向起始地址的指针内存块,因此 (2) 当不再需要它时可以释放。
您必须使用内存错误检查程序来确保您不会尝试访问内存或写入超出/超出分配块的边界,尝试读取或基于未初始化的值进行条件跳转,最后,以确认您释放了已分配的所有内存。
对于 Linux,valgrind 是正常的选择。每个平台都有类似的内存检查器。它们都易于使用,只需通过它运行您的程序即可。
$ valgrind ./bin/struct_ptr_alloc
==5051== Memcheck, a memory error detector
==5051== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==5051== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==5051== Command: ./bin/struct_ptr_alloc
==5051==
Enter # of Students: 2
Enter #'s of Subjects for Student 0: 2
Enter Mark for Subject 1: 99
Enter Mark for Subject 2: 100
Enter #'s of Subjects for Student 1: 2
Enter Mark for Subject 1: 89
Enter Mark for Subject 2: 92
The roll # of student 1 are 1
The roll # of student 2 are 2
==5051==
==5051== HEAP SUMMARY:
==5051== in use at exit: 0 bytes in 0 blocks
==5051== total heap usage: 5 allocs, 5 frees, 2,096 bytes allocated
==5051==
==5051== All heap blocks were freed -- no leaks are possible
==5051==
==5051== For counts of detected and suppressed errors, rerun with: -v
==5051== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始终确认您已释放已分配的所有内存并且没有内存错误。
查看一下,如果您还有其他问题,请告诉我。