我试图找出堆上和堆栈上的结构之间的区别。我有以下结构,书籍,作者和书架。 Book有多位作者,而Shelf有多本书。
struct Author {
char name[NAME_LENGTH];
};
struct Book {
char title[TITLE_LENGTH];
struct Author authors[AUTHORS_PER_BOOK];
int author_count;
};
struct Shelf {
struct Book books[BOOKS_PER_SHELF];
int book_count;
};
我有一堆创建Author和Book结构的函数,具有指定的名称和标题。以及添加作者预订的功能。我理解C是严格按值传递的,所以我在add_authors_to_book函数中使用了指向该书的指针。这些函数是在本地创建的,我假设它们在堆栈中(?)。
struct Author new_author(char name[]) {
struct Author author;
strcpy(author.name, name);
return author;
}
struct Book new_book(char title[]) {
struct Book book;
strcpy(book.title, title);
book.author_count = 0;
return book;
}
void print_book(struct Book book) {
printf("%s\nby", book.title);
int i, n;
for (i = 0, n = book.author_count; i < n; i++) {
printf(" %s,", book.authors[i].name);
}
printf("\b.\n");
}
void add_author_to_book(struct Book *book, struct Author author) {
book->authors[book->author_count] = author;
book->author_count++;
}
我希望货架在堆上。我正在为它分配内存并在下面释放它。
struct Shelf *new_shelf() {
struct Shelf *shelf = malloc(sizeof(struct Shelf));
shelf->book_count = 0;
return shelf;
}
void delete_shelf(struct Shelf *shelf) {
free(shelf);
}
void print_shelf(struct Shelf *shelf) {
printf("Shelf has the %d book(s),\n", shelf->book_count);
int i, n;
for (i = 0, n = shelf->book_count; i < n; i++) {
print_book(shelf->books[i]);
}
}
我的问题是将书籍添加到书架上。下面我将书籍结构分配给书架的最后一个索引。这个struct Book驻留在堆上还是堆栈上? C会在将其传递给add_book_to_shelf时自动创建包含作者的整个Book结构的克隆吗?传递值是否适用于这种嵌套结构?
另外,你如何解放书籍及其作者所使用的记忆?
void add_book_to_shelf(struct Shelf *shelf, struct Book book) {
shelf->books[shelf->book_count] = book;
shelf->book_count++;
}
这是我的测试代码,
int main(int argc, char *argv[]) {
struct Shelf *shelf = new_shelf();
struct Book book = new_book("Freakonomics");
add_author_to_book(&book, new_author("Stephen Dubner"));
add_author_to_book(&book, new_author("Steven Levitt"));
add_book_to_shelf(shelf, book);
print_shelf(shelf);
delete_shelf(shelf);
return 0;
}
答案 0 :(得分:2)
答案是书本身就在书架上。由于您将架构结构声明为直接包含书籍,因此它包含将书籍存储在其中的所需空间。因此,将书籍分配到书架实际上会将其值复制到书架中。因此,如果架子在堆栈上,那么书就会在堆栈上,反之亦然。
答案 1 :(得分:1)
你正在add_book_to_shelf中复制这本书,这意味着它将在堆上。
你在main中创建的书将在堆栈中(因为它是一个自动变量),但是在add_book_to_shelf中,书被复制到books数组中,该数组被分配为堆上架子的一部分。
答案 2 :(得分:1)
关于你对free()的使用, 只需免费(货架)就可以使用您的测试代码。 shelf是一个指针,其数据被动态分配给堆,这就是为什么需要使用free()删除它。您不必使用免费(shelf-&gt; books [i]),因为您没有动态分配books数组。您自动在数组中声明BOOKS_PER_SHELF元素。这可能对内存管理效率不高,但它使您的取消分配非常简单和可读。