2012-05-30 129 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; 
}