2

我试图弄清楚堆上的结构和堆栈上的结构之间的区别。我有以下结构,用于书籍、作者和书架。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]);
    }
}

我的问题是关于将书籍添加到书架上。下面我将 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;
}
4

3 回答 3

2

答案是书本身就在书架上。由于您将书架结构声明为直接包含书籍,因此它包含在其中存储书籍所需的完整空间。因此,将书分配到书架实际上会将其值复制到书架中。因此,如果书架在堆栈上,则书将在堆栈上,反之亦然。

于 2012-09-13T03:45:14.967 回答
1

关于您对 free() 的使用,只需 free(shelf) 即可用于您的测试代码。Shelf 是一个指针,其数据被动态分配到堆中,这就是为什么需要使用 free() 删除它的原因。您不必使用 free(shelf->books[i]) 因为您没有动态分配 books 数组。您在数组中自动声明 BOOKS_PER_SHELF 元素。这对于内存管理可能效率不高,但它使您的取消分配非常简单和可读。

于 2012-09-13T05:39:41.350 回答
1

您正在复制 add_book_to_shelf 中的书,这意味着它将在堆上。

您在 main 中创建的书将在堆栈上,(因为它是一个自动变量),但在 add_book_to_shelf 中,该书被复制到书数组中,该数组作为堆上书架的一部分分配。

于 2012-09-13T03:44:45.390 回答