2012-09-13 136 views
2

我想弄清楚堆和堆栈上的结构之间的区别。我有以下结构,用于书籍,作者和书架。书有多个作者,书架有多本书。将堆栈结构存储在堆vs栈上

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驻留在堆或Stack上的什么位置?当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; 
} 

回答

1

你复制书中add_book_to_shelf,这意味着它将是在堆上。

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

+0

谢谢。所以这本书通过add_author_to_book中的按值传递自动复制和分配在堆上。我们是否必须手动释放这些内存,或者是否可以自动释放(内存)? – mathguy80

+0

免费的书架将删除堆中包含的所有书籍,因为它们是书架的一部分 – wich

+0

非常好,谢谢。 – mathguy80

2

答案是,这本书驻留在书架本身。由于您声明书架结构直接包含书籍,因此它包含将书籍存储在书架中的完整空间。因此,将这本书分配到一个书架上实际上是将它的值复制到书架上。所以如果书架在书架上,那么书会放在书架上,反之亦然。

+0

谢谢。但是我想要堆上的架子,而不是堆叠。我正在使用malloc手动执行此操作...困惑... – mathguy80

+0

啊!我明白你的意思。这两种方式都行得通,书就在书架内。得到它了。谢谢! – mathguy80

1

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

+1

谢谢,这有帮助。 – mathguy80