2013-10-13 61 views
1

在捷思銳的流行(意見)系列,在章「堆和棧」的代碼爲DATABSE如下學習C艱辛的道路章堆和棧代碼

請注意,這是Zed的肖氏代碼

struct Address { 
    int id; 
    int set; 
    char name[MAX_DATA]; 
    char email[MAX_DATA]; 
}; 

struct Database { 
    struct Address rows[MAX_ROWS]; 
}; 

struct Connection { 
    FILE *file; 
    struct Database *db; 
}; 




struct Connection *Database_open(const char *filename, char mode) 
{ 
    struct Connection *conn = malloc(sizeof(struct Connection)); 
    if(!conn) die("Memory error"); 

    conn->db = malloc(sizeof(struct Database)); 
    if(!conn->db) die("Memory error"); 

    if(mode == 'c') { 
     conn->file = fopen(filename, "w"); 
    } else { 
     conn->file = fopen(filename, "r+"); 

     if(conn->file) { 
      Database_load(conn); 
     } 
    } 

    if(!conn->file) die("Failed to open the file"); 

    return conn; 
} 



void Database_create(struct Connection *conn) 
{ 
    int i = 0; 

    for(i = 0; i < MAX_ROWS; i++) { 
     // make a prototype to initialize it 
     struct Address addr = {.id = i, .set = 0}; 
     // then just assign it 
     conn->db->rows[i] = addr; 
    } 
} 

我在他Database_create功能感到,他在形式結構地址獲分配的內存,當內存F爲已經獲分配爲創作 結構的數據庫,是陌生來電。

然後我通過這一思路推斷他稱爲malloc兩次,首先爲創建Connection分配堆內存,然後再次在結構Connection(即Databse)內創建結構類型的事實,也應該很奇怪。我推測可能是Zed知道並理解結構巢必須逐層構建。

就在發佈這個問題之前,我決定編寫一個簡單的嵌套結構類型,並嘗試通過一個malloc調用創建的最外層結構訪問結構層內的數據....我的推理是,如果我的想法認爲沒有必要通過層來構造嵌套結構層是真的,我可以不分段錯誤訪問嵌套數據。而我所做的

的代碼如下

#include<stdlib.h> 
#include<stdio.h> 




struct Killfly{ 

    char str[20]; 

}; 

struct wtf 
{ 
    struct Killfly a; 
}; 

struct wtf2{ 

    struct wtf k; 
}; 


int main(){ 
    struct wtf2*fly=malloc(sizeof(struct wtf2)); 
    printf("size of %ld \n",sizeof(*fly)); 
    fly->k.a.str[0]='a'; 
    //printf("size of wtf is %ld \n",sizeof(wtf)); 
    free(fly); 

    return 0; 

} 

,它沒有賽格寫故障

問題

爲啥Zed的地方多的malloc調用,爲什麼當他已經爲結構數據庫分配的空間,在功能Database_struct,在for循環中,他繼續呼籲基於堆棧結構地址對象和將它們放入所述類型的數組中?

+2

「那麼,爲什麼Zed的地方多的malloc調用」 - 他 –

+0

@EdHeal由線測試我相信人性,你的意思,有一個明顯的回答這個問題,我的思路是錯誤的? –

+0

因爲他想要更多的內存(這是'malloc'的目的) –

回答

3

Database_open()中有多個malloc調用,因爲struct Connection包含一個指向struct Database的指針,而不是直接合並struct Database。這可能已經完成,像這樣:

struct Connection { 
    FILE *file; 
    struct Database db;  // directly incorporate a `struct Database` 
}; 

實際上,這是你在你的struct wtf2例如做了什麼。有設計決定可以使它成爲一種方法,因爲各種原因可能比另一種更好。我不熟悉「Learn C the Hard Way」系列,所以我不能評論設計選擇是否討論得很好。

作爲使用基於堆棧地址對象初始化數組,這是C'S對象初始化的方便起見,在評論中提及作爲製備原型:

// make a prototype to initialize it 
    struct Address addr = {.id = i, .set = 0}; 

在C中,沒有這樣的東西作爲一個結構文字可以直接分配到conn->db->rows[i]。但是在struct object的聲明中,可以提供初始化程序來初始化該對象。所以這就是發生在這裏的事情 - 聲明一個struct Address對象僅僅用於提供指定初始化器的便利,然後立即將該對象分配給堆分配結構(這正是我們想要初始化的)。代碼的順序是或多或少相當於:

memset(&conn->db->rows[i], 0, sizeof(conn->db->rows[i])); 
    conn->db->rows[i].id = i; 
+0

啊我不好,我忽略了連接結構中的指針。 –