2015-06-01 4 views
7

Ho riscontrato un problema durante il tentativo di esprimere il puntatore a un tipo all'interno di una macro.Puntatore da digitare all'interno di una macro, C

Prendi questo semplice esempio.

#define INDEX_OF_DATA(data, type, index) \ 
    ((type *)data)[index] 

questo funziona:

INDEX_OF_DATA(buffer, float, 3); 

Dove questo non riesce:

INDEX_OF_DATA(buffer, float[2], 3); 

perché il cast dovrebbe essere (float(*)[2]).

C'è un modo per esprimere "il puntatore di un type", ... senza usare typeof? (che non è standard C).


Nota, ci sono naturalmente altri modi per far funzionare questo specifico esempio. cast per char e offset per sizeof(type) * index per esempio. Ma sono interessati ad un modo per esprimere pointer to type in C.

+2

Non penso sia possibile senza estensioni, ma sarei curioso di sapere se qualcuno ha un'idea migliore. – zwol

+0

C++ ha una soluzione migliore con l'inferenza di tipo, ma con C la tua scelta è prossima a nessuno – texasbruce

risposta

0

Se vogliamo conservare la macro originale, possiamo usare questo trucco:

#define INDEX_OF_DATA(data, type, index) ((type*)data)[index] 

struct mystruct { float f[2]; }; 
mystruct* p = &INDEX_OF_DATA(buffer, mystruct, 3); 

Purtroppo questa soluzione potrebbe essere influenzata da imbottitura struct quindi è meglio per controllare:

static_assert(sizeof(mystruct) == sizeof(float (*)[2]), "padding found"); 
+0

Sicuro che sia corretto? struct's può essere riempito. – ideasman42

+0

Questo non verrà nemmeno compilato in C – texasbruce

+0

@texasbruce Sì, hai ragione. Anche se la mia soluzione non è perfetta, può eventualmente stimolare altre e migliori soluzioni. – dlask

1

fare cose molto complicate con i tipi C può essere uno sport divertente, ma è estremamente confusa nel codice reale.

Per evitare di capovolgere troppo le espressioni complicate del puntatore, le persone usano spesso typedef!

Se si dispone di typedef tutti i tipi che si prevede di utilizzare con questa macro, non si verificheranno problemi. Osservare:

#include <stdlib.h> 

#define INDEX_OF_DATA(data, type, index) \ 
    ((type *)data)[index] 


int main(void) { 
    float (*buffer)[2] = malloc(4 * sizeof(float[2])); 

    typedef float t_f2arr[2]; 

    INDEX_OF_DATA(buffer, t_f2arr, 3)[0] = 1.1f; 

    return 0; 
} 

Questo fa esattamente ciò che si intendeva!