2012-05-09 30 views
12

Un uso comune di typedefs è di abilitare il "tipo" di una variabile per comunicare un'idea migliore dello scopo di una variabile senza ridefinire la struttura di archiviazione dietro di esso.Identificativi del typedef e del formato printf

Tuttavia, sto anche vedendo typedefs come un modo per modificare la struttura di archiviazione per una classe di variabili in un colpo solo.

Ad esempio, se definire

typedef uint32_t my_offset_t 

e hanno variabili del tipo my_offset_t, la commutazione del codice-base da uint32_t a char o uint64_t è semplice come cambiare una riga e ricompilazione (supponendo ho utilizzato sizeof anziché taglie codificate), tranne nel caso di printf/scanf.

Esiste un modo per scambiare formato-committenti a seconda del tipo in qualche modo semplice, senza funzioni wrapper per printf/scanf, se-elses, o ifdefs?

Grazie!

Per chiunque sia interessato, sto modificando un LKM che utilizza offset a 16 bit per lavorare con offset a 32 bit, ma si vuole che sia in grado di andare a 64-bit (o qualcos'altro!) Compensazioni se necessario con modifiche minime.

risposta

9

È un lavoro complicato, ma il <inttypes.h> da C99 e successivi mostra il modo per farlo.

Per ciascuno dei tipi definiti, è necessario fornire un set appropriato di macro 'PRI' e 'SCN', facendo attenzione a evitare lo spazio dei nomi standardizzato.

Ad esempio, è possibile usare XYZ come prefisso specifica del progetto, e produrre:

XYZ_PRIx_my_offset_t 
XYZ_PRId_my_offset_t 
XYZ_PRIX_my_offset_t 
XYZ_PRIu_my_offset_t 
XYZ_PRIo_my_offset_t 

e gli equivalenti SCN. Inoltre, si potrebbe definire questi in termini di macro equivalenti per il tipo di base, in modo da:

#define XYZ_PRIx_my_offset_t PRIx32 
#define XYZ_PRId_my_offset_t PRId32 
#define XYZ_PRIX_my_offset_t PRIX32 
#define XYZ_PRIu_my_offset_t PRIu32 
#define XYZ_PRIo_my_offset_t PRIo32 

Nel codice, è costruire le stringhe di formato utilizzando i XYZ_PRIx_my_offset_t macro:

printf("Offset: 0x%.8" XYZ_PRIX_my_offset_t "\n", my_offset_value); 

Se successivamente è necessario modificare tutto a 64 bit, modificare il typedef e le definizioni di macro in modo appropriato e il resto del codice rimane "invariato". Se sei veramente attento, puoi diventare abbastanza vicino a completamente invariato.

Assicurati di compilare su entrambi i sistemi a 32 bit e 64 bit con un sacco di set di avvisi. GCC non avviserà in merito a problemi relativi alla piattaforma corrente, ma potrebbero essere visualizzati sull'altro. (Ho appena corretto un codice pulito su 64-bit ma non pulito per 32-bit, ora utilizza una macro come XYZ_PRId_int4 anziché %d e si compila in modo pulito su entrambi.

7

Se guardate il mio earlier question on inttypes.h si può vedere come sistema definito identificatori di formato potrebbero essere utilizzati in concerto con typedef (via #define) per rendere specificatori di stampa personalizzati per i tipi personalizzati.

+0

Grazie per la risposta :) ho accettato l'altra, però, perché si tratta di una risposta più completa, nel caso in cui nessun altro è interessato a questa domanda. – Vanwaril

0

Un'altra soluzione è la conversione da e verso intmax_t per i tipi firmati e uintmax_t per i tipi senza segno. Per esempio:

printf("%ju\n", (uintmax_t)n); 

funzionerà correttamente se n è di qualsiasi tipo senza segno.

Per le funzioni *scanf(), è necessario leggere in un oggetto temporaneo e quindi assegnare.

(Premesso che la libreria di runtime supporta queste funzioni.)

Problemi correlati