typedef struct _chess {
int **array;
int size;
struct _chess *parent;
} chess;
und ich habe:
typedef struct _chess *Chess;
Jetzt möchte ich ein Array mit dynamischer Länge erstellen, um Zeiger auf die Schachstruktur zu speichern, also mache ich Folgendes:
Chess array [] = malloc(size * sizeof(Chess));
Dies gibt mir einen Fehler: ungültiger Initialisierer.
Und wenn ich die fallen lasse [] und mach das:
Chess array = malloc(size * sizeof(Chess));
es wird ohne Fehler kompiliert, aber wenn ich versuche, ein Element dieses Arrays auf NULL zu setzen, indem ich Folgendes mache:
array[i]=NULL;
Ich erhalte eine Fehlermeldung: Inkompatible Typen beim Zuweisen zum Typ „struct _chess“ vom Typ „void *“
Irgendeine Idee, was ich falsch mache? Vielen Dank.
WARUM typedef die Struktur? es hat bereits einen eindeutigen Typ.
– Benutzer82238
30. Mai 2012 um 7:15 Uhr
@ user82238 Sie müssen also nicht tippen struct bei der Verwendung des Typs.
– Tyilo
7. Juni 2013 um 16:27 Uhr
Hören Sie auf, Zeiger-Typedefs zu verwenden, Sie verwirren sich nur selbst. chess *array = malloc(size * sizeof *array);.
– MM
14. März 2014 um 0:42 Uhr
Ebenfalls, NULL kann nicht a zugeordnet werden chess. Das einzige, was Sie einer Struktur zuweisen können, ist eine andere Struktur desselben Typs. Vielleicht meinst du sowas wie: chess blank = { 0 }; array[i] = blank;
– MM
14. März 2014 um 0:44 Uhr
CB Bailey
array ist ein etwas irreführender Name. Für ein dynamisch zugewiesenes Array von Zeigern gilt: malloc gibt einen Zeiger auf einen Speicherblock zurück. Sie müssen verwenden Chess* und nicht Chess[] um den Zeiger auf Ihr Array zu halten.
/* create new struct chess */
array[i] = malloc(sizeof(struct chess));
/* set up its members */
array[i]->size = 0;
/* etc. */
Vielen Dank! Das hat es für mich behoben! Würden Sie bitte erklären, warum Chess nicht funktioniert?[] Arbeit? Ich bin jetzt aber verwirrt [] und * sind dasselbe.
– MinaHany
30. Mai 2012 um 7:20 Uhr
@MinaHany [] ist ein Array, das den eigentlichen Inhalt enthält. * ist ein Zeiger auf den Inhalt. Zugriff und Verwendung sind gleich, aber die Speicherdarstellung ist völlig anders.
– glglgl
30. Mai 2012 um 7:24 Uhr
entspannen
Es gibt viel typedef hier los. Ich persönlich bin dagegen, “das Sternchen auszublenden”, dh typedef:ing Zeiger gibt etwas ein, das nicht wie ein Zeiger aussieht. In C sind Zeiger ziemlich wichtig und wirken sich wirklich auf den Code aus, es gibt viele Unterschiede zwischen ihnen foo und foo *.
Viele der Antworten sind darüber auch verwirrt, denke ich.
Ihre Zuordnung eines Arrays von Chess Werte, die Zeiger auf Werte vom Typ sind chess (wieder ein sehr verwirrende Nomenklatur, die ich wirklich nicht empfehlen kann) sollte so aussehen:
Chess *array = malloc(n * sizeof *array);
Dann müssen Sie die eigentlichen Instanzen initialisieren, indem Sie Folgendes wiederholen:
for(i = 0; i < n; ++i)
array[i] = NULL;
Dies setzt voraus, dass Sie den Instanzen keinen Speicher zuweisen möchten, Sie möchten nur ein Array von Zeigern, bei denen alle Zeiger anfänglich auf nichts zeigen.
Wenn Sie Speicherplatz zuweisen möchten, wäre die einfachste Form:
Sehen Sie, wie die sizeof Nutzung ist 100% konsistent, und noch nie beginnt, explizite Typen zu erwähnen. Verwenden die Typinformationen, die Ihren Variablen inhärent sind, und lassen Sie den Compiler sich darum kümmern, welcher Typ welcher ist. Wiederholen Sie sich nicht.
Natürlich führt das oben Genannte zu unnötig vielen Anrufen malloc(); Je nach Nutzungsmuster ist es möglich, alle oben genannten Aufgaben mit nur einem Aufruf von zu erledigen malloc(), nach Berechnung der benötigten Gesamtgröße. Dann müssten Sie noch durchgehen und die initialisieren array[i] Zeiger, die natürlich in den großen Block zeigen.
hmm.. Ich habe Schach gemacht *array = malloc(size * sizeof(Chess)); und dann for (i=0; i
– MinaHany
30. Mai 2012 um 7:42 Uhr
Ja, das ist in Ordnung, wenn alles, was Sie wollen, ein Array von Zeigern ist, die Sie später auf einige Instanzen setzen, die Sie herumliegen haben. Ich habe geändert, um NULL-init als Standardfall hinzuzufügen.
– abschalten
30. Mai 2012 um 7:48 Uhr
IMHO sieht das besser aus:
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));
}
Ich denke, ich würde dies verwenden, wenn ich möchte, dass das Array tatsächliche Strukturen enthält, nicht nur Zeiger auf sie. Ist das richtig?
– MinaHany
30. Mai 2012 um 7:20 Uhr
In diesem Code-Array befinden sich Zeiger, nicht die Objekte. Um ein Array von Strukturen zu erstellen, verwenden Sie struct _chess a[10]; //Array of ten structs _chess
– Außenseiter
30. Mai 2012 um 7:30 Uhr
Netzhaut
Ich stimme @maverik oben zu, ich ziehe es vor, die Details nicht mit einer Typedef zu verbergen. Vor allem, wenn Sie versuchen zu verstehen, was vor sich geht. Ich ziehe es auch vor, alles zu sehen, anstatt nur einen teilweisen Codeausschnitt. Abgesehen davon ist hier ein Malloc und frei von einer komplexen Struktur.
Der Code verwendet den Leak-Detektor von ms visual studio, sodass Sie mit den potenziellen Leaks experimentieren können.
#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;
}
11453300cookie-checkmalloc ein Array von Strukturzeigernyes
WARUM typedef die Struktur? es hat bereits einen eindeutigen Typ.
– Benutzer82238
30. Mai 2012 um 7:15 Uhr
@ user82238 Sie müssen also nicht tippen
struct
bei der Verwendung des Typs.– Tyilo
7. Juni 2013 um 16:27 Uhr
Hören Sie auf, Zeiger-Typedefs zu verwenden, Sie verwirren sich nur selbst.
chess *array = malloc(size * sizeof *array);
.– MM
14. März 2014 um 0:42 Uhr
Ebenfalls,
NULL
kann nicht a zugeordnet werdenchess
. Das einzige, was Sie einer Struktur zuweisen können, ist eine andere Struktur desselben Typs. Vielleicht meinst du sowas wie:chess blank = { 0 }; array[i] = blank;
– MM
14. März 2014 um 0:44 Uhr