2012-09-13 132 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