Perché dobbiamo lanciare ciò che malloc restituisce?
Domanda
int length = strlen(src);
char *structSpace = malloc(sizeof(String) + length + 1);
String *string = (String*) structSpace;
int *string = (int*) structSpace;
* Ho creato una struttura chiamata String
Soluzione
Non lo fai. void*
eseguirà il cast implicito di tutto ciò di cui hai bisogno in C. Vedi anche le FAQ C sul motivo per cui si vorrebbe evitare esplicitamente il cast del ritorno di malloc in C. La risposta di Sinan illustra ulteriormente perché questo è stato seguito in modo incoerente.
Altri suggerimenti
Poiché malloc restituisce un puntatore a vuoto, vale a dire, sta semplicemente allocando blocchi di memoria senza tener conto dei dati che verranno archiviati lì. In C ++ il tuo vuoto restituito * non verrà implicitamente lanciato sul puntatore del tuo tipo. Nel tuo esempio, non hai lanciato ciò che malloc ha restituito. Malloc ha restituito un vuoto * che è stato implicitamente lanciato su un carattere *, ma nella riga successiva tu ... ok, non ha più molto senso.
L'elenco delle domande frequenti su C è una risorsa inestimabile: Perché alcuni codici trasmettono attentamente i valori restituiti da malloc al tipo di puntatore che viene allocato? .
Questo è uno dei pochi problemi che rende la frase " C ++ è un superset di C " non del tutto vero. In C, un puntatore void
può essere implicitamente proiettato su qualsiasi altro tipo di puntatore. Tuttavia, C ++ è un po 'più rigoroso con la sicurezza dei tipi, quindi è necessario eseguire il cast esplicito del valore restituito malloc
sul tipo appropriato. Di solito, questo non è un grosso problema, perché il codice C ++ tende a utilizzare new
anziché <=>, che non richiede la tipografia.
In C, il cast del risultato di malloc non è necessario e non dovrebbe essere fatto. In questo modo, ad esempio, è possibile nascondere l'errore di non avere #include <stdlib.h>
, quindi non si ha un prototipo di malloc nell'ambito. Questo, a sua volta, può portare ad altri errori e alla mancanza di portabilità (anche se i peggiori trasgressori al riguardo sono ora per lo più obsoleti).
In C ++, devi trasmettere il risultato di malloc per assegnarlo a un puntatore a qualsiasi tipo diverso da void. A meno che tu non abbia bisogno di scrivere codice che può essere compilato come C o C ++, tuttavia, dovresti generalmente evitare di usare malloc
in C ++ e allocare memoria usando new
.
Tendi a vedere questo tipo di codice C dai principianti (o dai programmatori C ++ :-)):
int main() {
int len = 40;
char *my_string = (char *) malloc(sizeof(char)*len);
return 0;
}
Questo è inutile e malvagio, puoi evitare il cast inutile includendo stdlib.h
#include <stdlib.h>
int main() {
int len = 40;
char *my_string = malloc(sizeof(char)*len);
return 0;
}
Dovresti considerare fortemente il casting dopo aver usato il comando malloc perché fornisce una maggiore portabilità e una maggiore compatibilità con altre parti del tuo programma. In caso contrario, si potrebbe correre il rischio di tipi di dati incompatibili che potrebbero causare errori.