2013-08-04 16 views
5

Ho il seguente codice nell'header Cerrore di malloc in struct (C)

typedef struct { 
    kiss_fft_scalar r; 
    kiss_fft_scalar i; 
} kiss_fft_cpx; 

E ho implementato il seguente codice nel programma di test

kiss_fft_cpx *fin = malloc(4*sizeof(kiss_fft_cpx)); 

e mi ha dato il messaggio di errore : "Un valore di tipo void non può essere utilizzato per inizializzare un'entità di tipo 'kiss_fft_ctx'".

Utilizzo il progetto di console Win32 di Visual Studio C/C++.

Qualcuno può dirmi come utilizzare correttamente il malloc qui? Grazie!

+0

possibile duplicato del [di conversione non valida dal 'vuoto \ *' a 'nodo \ *' \ [-fpermissive \]] (http://stackoverflow.com/questions/16793587/invalid-conversion-from-void-to -node-fpermissive) –

+1

Non penso che il messaggio di errore fosse 'nullo non può essere usato per inizializzare kiss_fft_ctx'. Penso che fosse 'void *' e 'kss_fft_ctx *'. Questi asterischi fanno una differenza ** BIG ** nel significato e nella comprensione della lingua. – abelenky

risposta

12

È necessario lanciare il tipo di ritorno come questo:

kiss_fft_cpx *fin = (kiss_fft_cpx*) malloc(4*sizeof(kiss_fft_cpx)); 

ma l'implicazione è che si sta compilando il codice come C++, piuttosto che C, perché questo è un errore di C++, piuttosto che un errore di C. Potresti voler controllare la tua estensione di file e/o le tue impostazioni del compilatore.

Se davvero sei utilizzando C++, si dovrebbe ad un minimo impiego new piuttosto che malloc:

kiss_fft_cpx *fin = new kiss_fft_cpx[4]; 

e idealmente ripensare se è necessario essere la creazione di oggetti in modo dinamico come questo - si potrebbe utilizzare un std::vector o simile?

+2

+1 per la nota su C++. –

+0

Cool, il problema è che devo usare un codice C programmato da altri nel mio progetto C++. Quindi, mi chiedo se sia anche possibile utilizzare altri schemi piuttosto che malloc per terminare l'allocazione della memoria. (Altrimenti, C++ sembra essere abbastanza stupido qui quando usiamo C in C++) – Cancan

+4

@Cancan Lo è, ma è meglio non farlo. Basta compilare come C invece. ** Non provate MAI a compilare il codice C come C++. ** Sono lingue diverse. –

3

In C è possibile eseguire il cast del puntatore del vuoto restituito da malloc. C fa questo per te ma puoi anche essere esplicito.

malloc restituisce un puntatore void void * oppure restituito da un programmatore in altri tipi di puntatore. Oppure il programmatore può contare su C per eseguire la conversione del tipo. Non è previsto che la conversione di tipo C mediante cast sia modificata.

Tuttavia, il codice C che si basa sul compilatore C può essere ostile e difficile da leggere. Un programmatore di sviluppo può aiutare i programmatori di manutenzione che alla fine dovranno leggere il codice.

L'aggiunta di un cast esplicito al valore restituito di malloc aiuta gli utenti che avranno a leggere il codice e determinare l'intenzione dell'autore. Questo è il vero vantaggio del cast esplicito del puntatore void restituito da malloc. Questa pratica di programmazione fa NON mis-dirige il compilatore o fa uso di qualche caratteristica del compilatore arcano che potrebbe cambiare.

I seguenti tre esempi evidenziano questa pratica di programmazione. Nel primo esempio, malloc (che è definito in <stdlib.h>) è espressamente trasmesso e alcuni lavori banali sono eseguiti .

#include <stdlib.h> 
    #define nr_chars 4 
    main() 
    { 
    char *data; 

    data = (char *) malloc(nr_chars*sizeof(char)); 

    *data++ = 'a'; 
    *data++ = 'b'; 
    *data++ = 'c'; 
    *data++ = '\0'; // it is allowed to go one past an array 

    data -= nr_chars; // back to the front of data 

    printf("%s\n", data); 
    // prints abc at the console 

    } 

In questo secondo esempio, l'unica differenza è che <stdlib.h> sia commentata. Il codice viene ancora eseguito e produce lo stesso risultato. Ora, il "perché" del perché questo funziona è abbastanza diretto. Quando C non trova il prototipo per una funzione, presuppone che la funzione restituisca un int, ma malloc restituisce un puntatore vuoto.In questo caso il cast esplicito ha indicato al compilatore C, nonché all'unità di carbonio della sorgente, che il valore restituito da malloc deve essere convertito in un puntatore di caratteri.

//#include <stdlib.h> 
    #define nr_chars 4 
    main() 
    { 
    char *data; 

    data = (char *) malloc(nr_chars*sizeof(char)); 

    *data++ = 'a'; 
    *data++ = 'b'; 
    *data++ = 'c'; 
    *data++ = '\0'; // it is allowed to go one past an array 

    data -= nr_chars; // back to the front of data 

    printf("%s\n", data); 
    // prints abc at the console 

    } 

L'ultimo esempio (yeah) non emette il cast e non include <stdlib.h>. Sia l'editor di Eclipse che il compilatore si lamentano di questo codice (come dovrebbero). Il messaggio di compilatore è

..\main.c(18) : warning C4047: '=' : 'char *' differs in levels of indirection from 'int' 

e il codice sorgente è:

//#include <stdlib.h> 
    #define nr_chars 4 
    main() 
    { 
    char *data; 

    data = malloc(nr_chars*sizeof(char)); 

    *data++ = 'a'; 
    *data++ = 'b'; 
    *data++ = 'c'; 
    *data++ = '\0'; // it is allowed to go one past an array 

    data -= nr_chars; // back to the front of data 

    printf("%s\n", data); 
    // compiler displays a "warning" and prints abc at the console 

    } 

Cambiare esempio 3 per includere risultati in nessun avviso e il programma viene eseguito come previsto. Tuttavia, entrambi gli esempi 2 e 3 sono privi del cast esplicito e nel corso della vita del codice scritto in questo stile tale codice sarà più costoso e più probabile che venga modificato in modo errato dagli umani (quindi la spesa aggiuntiva) rispetto all'utilizzo esplicito di cast supportati da C-compilatori.