2010-02-25 44 views
1

我已經在我的哈希表結構如下:將結構初始化爲指針還是沒有區別?

typedef char *HashKey; 
typedef int HashValue; 

typedef struct sHashElement { 
    HashKey key; 
    HashValue value; 
} HashElement; 

typedef struct sHashTable { 
    HashElement *items; 
    float loadFactor; 
} HashTable; 

我從來沒有想過這個問題到現在爲止,但我只是意識到有兩種方式我怎麼可以用這個:

選擇1:

void hashInitialize(HashTable *table, int tabSize) { 
    table->items = malloc(sizeof(HashElement) * tabSize); 

    if(!table->items) { 
     perror("malloc"); 
     exit(1); 
    } 

    table->items[0].key = "AAA"; 
    table->items[0].value = 45; 
    table->items[1].key = "BBB"; 
    table->items[1].value = 82; 

    table->loadFactor = (float)2/tabSize; 
} 


int main(void) { 
    HashTable t1; 
    int i; 

    hashInitialize(&t1, HASHSIZE); 

    for(i = 0; i < HASHSIZE - 1; i++) { 
     printf("PAIR(%d): %s, %d\n", i+1, t1.items[i].key, t1.items[i].value); 
    } 

    printf("LOAD FACTOR: %.2f\n", t1.loadFactor); 

    return 0; 
} 

替代方法2:

void hashInitialize(HashTable **table, int tabSize) { 
    *table = malloc(sizeof(HashTable)); 

    if(!*table) { 
     perror("malloc"); 
     exit(1); 
    } 

    (*table)->items = malloc(sizeof(HashElement) * tabSize); 

    if(!(*table)->items) { 
     perror("malloc"); 
     exit(1); 
    } 

    (*table)->items[0].key = "AAA"; 
    (*table)->items[0].value = 45; 
    (*table)->items[1].key = "BBB"; 
    (*table)->items[1].value = 82; 

    (*table)->loadFactor = (float)2/tabSize; 
} 


int main(void) { 
    HashTable *t1 = NULL; 
    int i; 

    hashInitialize(&t1, HASHSIZE); 

    for(i = 0; i < HASHSIZE - 1; i++) { 
     printf("PAIR(%d): %s, %d\n", i+1, t1->items[i].key, t1->items[i].value); 
    } 

    printf("LOAD FACTOR: %.2f\n", t1->loadFactor); 

    return 0; 
} 

問題1:它們似乎都產生了相同的結果。在main上,這兩個示例都會打印右鍵/值對。那麼,除了語法更改(使用(*table)而不是table)之外,它們之間究竟有什麼不同,爲HashTable結構分配內存的額外代碼以及HashTable指針的聲明?

我最近一直在編寫一些數據結構,如堆棧,鏈表,二叉搜索樹和現在的散列表。對於他們所有人,我一直使用替代方案2.但現在我想我是否可以使用替代方案1並簡化代碼,去除大部分全部都在使用的*&

但我在問這個問題,以瞭解兩種方法之間的差異,以及如果以及爲什麼,我應該使用另一種方法。

問題2:正如你可以在結構代碼中看到,HashKey是一個指針。但是,我沒有使用strdupmalloc爲該字符串分配空間。這是如何和爲什麼這樣工作?這可以嗎?在處理動態字符串時,我總是在適當的地方使用mallocstrdup,否則我會得到很多分段錯誤。但是這段代碼並沒有給我任何分段錯誤,我不明白爲什麼,如果我應該這樣做。

回答

2

首先兩種解決方案都是完全正確的!

選擇1:

你Hashtable是在主宣稱,這意味着結構是某處調用堆棧。如果你離開示波器,結構將被破壞。注意:在你的情況下,由於聲明是主要的,所以範圍在流程退出時結束。

備選方案2:

你必須在調用堆棧哈希表*(指針),所以你需要分配內存的結構。要做到這一點,你使用malloc。

在這兩種情況下,您的結構被正確分配。主要區別在於表演。在堆棧上分配性能要高得多,但不能進行動態分配。要做到這一點,你需要使用malloc。 所以,有些時候,你必須使用malloc,但是如果你想要做一個高性能的應用程序,儘量避免mallocing。

那夠清楚了嗎? :)

0

唯一的區別是內存來自何處 - 局部變量通常位於堆棧上,而mallocs通常來自堆棧。

+0

不完全正確。局部變量不是'malloc''。他們的內存取自堆棧。 – 2010-02-25 16:26:03

2

在替代方案1中,調用者將分配table,但是您的函數將分配其內容,這在內存管理方面並不總是一個好主意。備選方案2將所有分配保留在同一地點。

+0

順便說一句 - 在這兩個例子中,內存不是free'd – Ofir 2010-02-25 16:23:00

+0

我知道內存不是free'd,我仍然在構建它的過程中,這不是最終的代碼。 – 2010-02-25 16:27:32

2

如前所述,兩種方案的區別在於內存管理。在替代方案1中,您希望調用方在調用之前爲表分配內存;而在替代方法2中,只需要一個指針聲明來給你一個放置內存的地方,在你創建它之後。

對於問題2,簡單的答案是您正在給字符串分配一個常量。根據以下站點,分配是在編譯時設置的,而不是運行時。

http://publications.gbdirect.co.uk/c_book/chapter6/initialization.html

1

問題2: (* table) - > items [0] .key =「AAA」;

實際上把「AAA」放在內存中的只讀部分和char *鍵指向它,鍵指向的內容不能改變。

(*表) - >項目[0] .KEY [0] = 'A' 給出和錯誤

在這裏你可以找到關於它的進一步討論。

What is the difference between char s[] and char *s?