2012-05-30 49 views
12

Tôi có struct sau:malloc một mảng của con trỏ struct

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

và tôi có:

typedef struct _chess *Chess; 

Bây giờ, tôi muốn tạo một mảng có độ dài năng động để lưu trữ con trỏ đến cờ vua struct vì vậy tôi làm như sau:

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

Điều này mang lại cho tôi một lỗi: trình khởi tạo không hợp lệ.

Và nếu tôi thả [] và thực hiện điều này:

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

nó biên dịch mà không có lỗi nhưng khi tôi cố gắng thiết lập một phần tử của mảng này để NULL bằng cách thực hiện:

array[i]=NULL; 

tôi gặp lỗi: các loại không tương thích khi gán cho loại 'struct _chess' từ loại 'void *'

Bất kỳ ý tưởng nào tôi đang làm sai? Cảm ơn.

+0

WHY typedef the struct? nó có một kiểu duy nhất rồi. –

+1

@ user82238 Vì vậy, bạn không phải gõ 'struct' khi sử dụng loại. – Tyilo

+3

Ngừng sử dụng con trỏ typedefs, bạn chỉ là khó hiểu chính mình. 'chess * array = malloc (kích thước * sizeof * mảng);'. –

Trả lời

33

array là tên hơi gây nhầm lẫn. Đối với mảng con trỏ được phân bổ động, malloc sẽ trả về một con trỏ tới một khối bộ nhớ. Bạn cần sử dụng Chess* và không phải Chess[] để giữ con trỏ đến mảng của bạn.

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

và có lẽ sau:

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

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

Cảm ơn bạn! CÁi này đã sửa nó giúp tôi! Bạn vui lòng giải thích lý do tại sao Chess [] không hoạt động? Tôi đang bối rối bây giờ tôi mặc dù [] và * là những điều tương tự. – MinaHany

+0

@MinaHany '[]' là một mảng, giữ nội dung thực tế. '*' là một con trỏ đến nội dung. Truy cập và sử dụng là như nhau, nhưng biểu diễn bộ nhớ hoàn toàn khác nhau. – glglgl

0

IMHO, điều này có vẻ tốt hơn:

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

Tôi nghĩ rằng tôi sẽ sử dụng này nếu tôi muốn mảng để giữ cấu trúc thực tế không chỉ con trỏ cho họ. Có đúng không? – MinaHany

+0

Trong mảng mã này giữ con trỏ, không phải đối tượng. Để tạo một mảng các cấu trúc sử dụng 'struct _chess a [10]; // Mảng mười cấu trúc _chess' – maverik

18

Có rất nhiều typedef xảy ra ở đây. Cá nhân tôi chống lại "ẩn dấu sao", tức là typedef: nhập các loại con trỏ vào thứ gì đó không giống như con trỏ. Trong C, con trỏ là khá quan trọng và thực sự ảnh hưởng đến mã, có rất nhiều sự khác biệt giữa foofoo *.

Nhiều câu trả lời cũng bị nhầm lẫn về điều này, tôi nghĩ vậy.

phân bổ của bạn của một mảng của Chess giá trị, mà là con trỏ đến giá trị của loại chess (một lần nữa, một rất khó hiểu thuật ngữ mà tôi thực sự không thể khuyên bạn) nên được như thế này:

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

Sau đó, bạn cần phải khởi tạo các phiên bản thực tế, bằng cách lặp:

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

Giả định bạn không muốn cấp phát bộ nhớ cho các trường hợp, bạn chỉ muốn một mảng con trỏ ith tất cả các con trỏ ban đầu chỉ vào không có gì.

Nếu bạn muốn bố trí không gian, hình thức đơn giản nhất sẽ là:

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

Xem cách sử dụng sizeof là phù hợp 100%, và không bao giờ bắt đầu đề cập đến loại rõ ràng. Sử dụng thông tin loại vốn có trong biến của bạn và để trình biên dịch lo lắng về loại nào. Đừng lặp lại chính mình.

Tất nhiên, ở trên, số lượng cuộc gọi không cần thiết lớn đến malloc(); tùy thuộc vào các mẫu sử dụng, có thể thực hiện tất cả những điều trên chỉ bằng một cuộc gọi đến malloc(), sau khi tính toán tổng kích thước cần thiết. Sau đó, bạn vẫn cần phải đi qua và khởi tạo các con trỏ array[i] để trỏ vào khối lớn, tất nhiên.

+7

+1 cho 'chống lại' ẩn dấu hoa thị "'. – glglgl

+0

hmm .. Tôi đã làm Cờ vua * mảng = malloc (kích thước * sizeof (Cờ vua)); và sau đó cho (i = 0; i MinaHany

+0

Vâng, đó là tốt, nếu tất cả các bạn muốn là một mảng của con trỏ mà sau này bạn thiết lập một số trường hợp mà bạn đã nằm xung quanh. Tôi đã sửa đổi để thêm NULL-init làm trường hợp mặc định. – unwind

0

Tôi đồng ý với @maverik ở trên, tôi không muốn ẩn chi tiết bằng typedef. Đặc biệt là khi bạn đang cố gắng để hiểu những gì đang xảy ra. Tôi cũng thích xem mọi thứ thay vì một đoạn mã một phần. Với điều đó nói, đây là một malloc và miễn phí của một cấu trúc phức tạp.

Mã sử ​​dụng trình phát hiện rò rỉ studio trực quan của MS để bạn có thể thử nghiệm với các rò rỉ tiềm ẩn.

#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; 
} 
Các vấn đề liên quan