2012-05-30 127 views
12

的陣列我有以下結構:malloc的結構指針

typedef struct _chess { 
    int **array; 
    int size; 
    struct _chess *parent; 
} chess; 

和我有:

typedef struct _chess *Chess; 

現在,我想創建動態長度的數組的指針存儲到國際象棋結構,所以我做以下幾點:

Chess array [] = malloc(size * sizeof(Chess)); 

這給了我一個錯誤:無效初始值設定項。

如果我把[]和做到這一點:

Chess array = malloc(size * sizeof(Chess)); 

它編譯沒有錯誤,但是當我嘗試這樣做,以設置該數組爲NULL的元素:

array[i]=NULL; 

我從類型'void *'分配類型'struct _chess'時出現錯誤:不兼容類型

任何想法我做錯了什麼? 謝謝。

+0

WH爲什麼typedef結構?它已經有了一個獨特的類型。 – 2012-05-30 07:15:51

+1

@ user82238所以你不必在使用類型時輸入'struct'。 – Tyilo

+3

停止使用指針typedefs,你只是迷惑自己。 'chess * array = malloc(size * sizeof * array);'。 –

回答

33

array是一個有點誤導性的名字。對於動態分配的指針數組,malloc將返回一個指向內存塊的指針。您需要使用Chess*而不是Chess[]來保存指向您陣列的指針。

Chess *array = malloc(size * sizeof(Chess)); 
array[i] = NULL; 

也許以後:

/* create new struct chess */ 
array[i] = malloc(sizeof(struct chess)); 

/* set up its members */ 
array[i]->size = 0; 
/* etc. */ 
+0

謝謝!這爲我修好了! 你能解釋爲什麼不不Chess []工作?我現在很困惑,雖然[]和*是相同的東西。 – MinaHany

+0

@MinaHany'[]'是一個包含實際內容的數組。 '*'是指向內容的指針。訪問和使用是相同的,但內存表示是完全不同的。 – glglgl

0

恕我直言,這看起來更好:

Chess *array = malloc(size * sizeof(Chess)); // array of pointers of size `size` 

for (int i =0; i < SOME_VALUE; ++i) 
{ 
    array[i] = (Chess) malloc(sizeof(Chess)); 
} 
+0

我想我會使用這個,如果我想要數組來保存實際的結構不僅僅是指向它們。是對的嗎? – MinaHany

+0

在這個代碼數組保存指針,而不是對象。爲了使結構數組使用'struct _chess a [10]; //十個結構數組_chess' – maverik

18

有很多的typedef怎麼回事。就我個人而言,我反對「隱藏星號」,即typedef:將指針類型轉換成看起來不像指針的東西。在C語言中,指針非常重要,並且確實會影響代碼,foofoo *之間有很大的區別。

我想,很多答案也讓我感到困惑。

Chess值,它是指向chess類型的值數組的分配(再次,我真的不能推薦一個非常混亂的命名)應該是這樣的:

Chess *array = malloc(n * sizeof *array); 

然後,你需要初始化的實際情況,通過循環:

for(i = 0; i < n; ++i) 
    array[i] = NULL; 

這是假設你不想分配任何內存的情況下,你只是想指針w的數組所有的指針最初都沒有指向任何東西。

如果你想分配空間,最簡單的形式是:

for(i = 0; i < n; ++i) 
    array[i] = malloc(sizeof *array[i]); 

sizeof使用率是如何100%一致,從未開始提明確的類型。 使用變量中固有的類型信息,並讓編譯器擔心哪個類型是哪個。不要重複自己。

當然,上述操作對malloc()進行了不必要的大量調用;取決於使用模式,在計算所需的總大小後,只需致電malloc()即可完成上述所有操作。然後,當然,您仍然需要完成並初始化指向大塊的指針。

+7

+1代表'反對'隱藏星號''。 – glglgl

+0

hmm .. 我做過國際象棋*數組= malloc(size * sizeof(國際象棋));對於(i = 0; i <大小; i ++)數組[i] = NULL;對於(i = 0; i <大小; i ++) 然後 。 } 及以後的代碼數組[i] = Chess1; 並且它在沒有在循環中執行第二個malloc的情況下工作正常。 爲什麼我需要另一個循環malloc如果我的數組只保存指針?我會需要它,如果數組實際上持有結構malloc數組第一,然後malloc結構在所有數組[我]或我想。我現在很困惑。 – MinaHany

+0

是的,這很好,如果你想要的是一個指針數組,你稍後設置一些實例,你有四處閒逛。我修改爲添加NULL-init作爲默認情況。 – unwind

0

我同意上面的@maverik,我不想用typedef隱藏細節。特別是當你試圖理解正在發生的事情時。我也喜歡看到一切,而不是部分代碼片段。這就是說,這裏是一個malloc,沒有複雜的結構。

該代碼使用ms visual studio泄漏檢測器,因此您可以嘗試潛在的泄漏。

#include "stdafx.h" 

#include <string.h> 
#include "msc-lzw.h" 

#define _CRTDBG_MAP_ALLOC 
#include <stdlib.h> 
#include <crtdbg.h> 



// 32-bit version 
int hash_fun(unsigned int key, int try_num, int max) { 
    return (key + try_num) % max; // the hash fun returns a number bounded by the number of slots. 
} 


// this hash table has 
// key is int 
// value is char buffer 
struct key_value_pair { 
    int key; // use this field as the key 
    char *pValue; // use this field to store a variable length string 
}; 


struct hash_table { 
    int max; 
    int number_of_elements; 
    struct key_value_pair **elements; // This is an array of pointers to mystruct objects 
}; 


int hash_insert(struct key_value_pair *data, struct hash_table *hash_table) { 

    int try_num, hash; 
    int max_number_of_retries = hash_table->max; 


    if (hash_table->number_of_elements >= hash_table->max) { 
     return 0; // FULL 
    } 

    for (try_num = 0; try_num < max_number_of_retries; try_num++) { 

     hash = hash_fun(data->key, try_num, hash_table->max); 

     if (NULL == hash_table->elements[hash]) { // an unallocated slot 
      hash_table->elements[hash] = data; 
      hash_table->number_of_elements++; 
      return RC_OK; 
     } 
    } 
    return RC_ERROR; 
} 


// returns the corresponding key value pair struct 
// If a value is not found, it returns null 
// 
// 32-bit version 
struct key_value_pair *hash_retrieve(unsigned int key, struct hash_table *hash_table) { 

    unsigned int try_num, hash; 
    unsigned int max_number_of_retries = hash_table->max; 

    for (try_num = 0; try_num < max_number_of_retries; try_num++) { 

     hash = hash_fun(key, try_num, hash_table->max); 

     if (hash_table->elements[hash] == 0) { 
      return NULL; // Nothing found 
     } 

     if (hash_table->elements[hash]->key == key) { 
      return hash_table->elements[hash]; 
     } 
    } 
    return NULL; 
} 


// Returns the number of keys in the dictionary 
// The list of keys in the dictionary is returned as a parameter. It will need to be freed afterwards 
int keys(struct hash_table *pHashTable, int **ppKeys) { 

    int num_keys = 0; 

    *ppKeys = (int *) malloc(pHashTable->number_of_elements * sizeof(int)); 

    for (int i = 0; i < pHashTable->max; i++) { 
     if (NULL != pHashTable->elements[i]) { 
      (*ppKeys)[num_keys] = pHashTable->elements[i]->key; 
      num_keys++; 
     } 
    } 
    return num_keys; 
} 

// The dictionary will need to be freed afterwards 
int allocate_the_dictionary(struct hash_table *pHashTable) { 


    // Allocate the hash table slots 
    pHashTable->elements = (struct key_value_pair **) malloc(pHashTable->max * sizeof(struct key_value_pair)); // allocate max number of key_value_pair entries 
    for (int i = 0; i < pHashTable->max; i++) { 
     pHashTable->elements[i] = NULL; 
    } 



    // alloc all the slots 
    //struct key_value_pair *pa_slot; 
    //for (int i = 0; i < pHashTable->max; i++) { 
    // // all that he could see was babylon 
    // pa_slot = (struct key_value_pair *) malloc(sizeof(struct key_value_pair)); 
    // if (NULL == pa_slot) { 
    //  printf("alloc of slot failed\n"); 
    //  while (1); 
    // } 
    // pHashTable->elements[i] = pa_slot; 
    // pHashTable->elements[i]->key = 0; 
    //} 

    return RC_OK; 
} 


// This will make a dictionary entry where 
// o key is an int 
// o value is a character buffer 
// 
// The buffer in the key_value_pair will need to be freed afterwards 
int make_dict_entry(int a_key, char * buffer, struct key_value_pair *pMyStruct) { 

    // determine the len of the buffer assuming it is a string 
    int len = strlen(buffer); 

    // alloc the buffer to hold the string 
    pMyStruct->pValue = (char *) malloc(len + 1); // add one for the null terminator byte 
    if (NULL == pMyStruct->pValue) { 
     printf("Failed to allocate the buffer for the dictionary string value."); 
     return RC_ERROR; 
    } 
    strcpy(pMyStruct->pValue, buffer); 
    pMyStruct->key = a_key; 

    return RC_OK; 
} 


// Assumes the hash table has already been allocated. 
int add_key_val_pair_to_dict(struct hash_table *pHashTable, int key, char *pBuff) { 

    int rc; 
    struct key_value_pair *pKeyValuePair; 

    if (NULL == pHashTable) { 
     printf("Hash table is null.\n"); 
     return RC_ERROR; 
    } 

    // Allocate the dictionary key value pair struct 
    pKeyValuePair = (struct key_value_pair *) malloc(sizeof(struct key_value_pair)); 
    if (NULL == pKeyValuePair) { 
     printf("Failed to allocate key value pair struct.\n"); 
     return RC_ERROR; 
    } 


    rc = make_dict_entry(key, pBuff, pKeyValuePair); // a_hash_table[1221] = "abba" 
    if (RC_ERROR == rc) { 
     printf("Failed to add buff to key value pair struct.\n"); 
     return RC_ERROR; 
    } 


    rc = hash_insert(pKeyValuePair, pHashTable); 
    if (RC_ERROR == rc) { 
     printf("insert has failed!\n"); 
     return RC_ERROR; 
    } 

    return RC_OK; 
} 


void dump_hash_table(struct hash_table *pHashTable) { 

    // Iterate the dictionary by keys 
    char * pValue; 
    struct key_value_pair *pMyStruct; 
    int *pKeyList; 
    int num_keys; 

    printf("i\tKey\tValue\n"); 
    printf("-----------------------------\n"); 
    num_keys = keys(pHashTable, &pKeyList); 
    for (int i = 0; i < num_keys; i++) { 
     pMyStruct = hash_retrieve(pKeyList[i], pHashTable); 
     pValue = pMyStruct->pValue; 
     printf("%d\t%d\t%s\n", i, pKeyList[i], pValue); 
    } 

    // Free the key list 
    free(pKeyList); 

} 

int main(int argc, char *argv[]) { 

    int rc; 
    int i; 


    struct hash_table a_hash_table; 
    a_hash_table.max = 20; // The dictionary can hold at most 20 entries. 
    a_hash_table.number_of_elements = 0; // The intial dictionary has 0 entries. 
    allocate_the_dictionary(&a_hash_table); 

    rc = add_key_val_pair_to_dict(&a_hash_table, 1221, "abba"); 
    if (RC_ERROR == rc) { 
     printf("insert has failed!\n"); 
     return RC_ERROR; 
    } 
    rc = add_key_val_pair_to_dict(&a_hash_table, 2211, "bbaa"); 
    if (RC_ERROR == rc) { 
     printf("insert has failed!\n"); 
     return RC_ERROR; 
    } 
    rc = add_key_val_pair_to_dict(&a_hash_table, 1122, "aabb"); 
    if (RC_ERROR == rc) { 
     printf("insert has failed!\n"); 
     return RC_ERROR; 
    } 
    rc = add_key_val_pair_to_dict(&a_hash_table, 2112, "baab"); 
    if (RC_ERROR == rc) { 
     printf("insert has failed!\n"); 
     return RC_ERROR; 
    } 
    rc = add_key_val_pair_to_dict(&a_hash_table, 1212, "abab"); 
    if (RC_ERROR == rc) { 
     printf("insert has failed!\n"); 
     return RC_ERROR; 
    } 
    rc = add_key_val_pair_to_dict(&a_hash_table, 2121, "baba"); 
    if (RC_ERROR == rc) { 
     printf("insert has failed!\n"); 
     return RC_ERROR; 
    } 



    // Iterate the dictionary by keys 
    dump_hash_table(&a_hash_table); 

    // Free the individual slots 
    for (i = 0; i < a_hash_table.max; i++) { 
     // all that he could see was babylon 
     if (NULL != a_hash_table.elements[i]) { 
      free(a_hash_table.elements[i]->pValue); // free the buffer in the struct 
      free(a_hash_table.elements[i]); // free the key_value_pair entry 
      a_hash_table.elements[i] = NULL; 
     } 
    } 


    // Free the overall dictionary 
    free(a_hash_table.elements); 


    _CrtDumpMemoryLeaks(); 
    return 0; 
}