C'è una libreria che costruisco contro diverse piattaforme a 32 bit. Ora, le architetture a 64 bit devono essere supportate. Quali sono le strategie più generali per estendere il codice a 32 bit esistente per supportare architetture a 64 bit? Dovrei usare # ifdef o qualcos'altro?L'aggiunta del supporto a 64 bit al codice a 32 bit esistente è difficile?
risposta
La quantità di impegno richiesto dipenderà interamente dalla qualità del codice originale. Nel migliore dei casi non ci sarà alcuno sforzo se non quello di ricompilare. Nel peggiore dei casi dovrai dedicare molto tempo a rendere il tuo codice "64 bit clean".
problemi tipici sono:
- ipotesi circa le dimensioni di int/lungo/puntatore/etc
- assegnazione puntatori < => ints
- basandosi su argomento di default o conversioni risultato funzione (cioè senza prototipi di funzione)
- inappropriate formato printf/scanf prescrittori
- ipotesi relative alla dimensione/allineamento/imbottitura le strutture (in particolare in materia di file o di rete di I/o O l'interfacciamento con altre API, ecc)
- calchi inadeguati quando si fa l'aritmetica dei puntatori con scostamenti di byte
Semplicemente non fare affidamento sull'assunzione delle dimensioni della parola della macchina? usa sempre sizeof, stdint.h, ecc. A meno che tu non faccia affidamento su chiamate di librerie diverse per architetture diverse, non ci dovrebbe essere bisogno di #ifdefs.
La strategia più semplice è quello di costruire quello che hai con le impostazioni a 64 bit e testare il heck fuori di esso. Alcuni codici non hanno bisogno di cambiare affatto. Altro codice, di solito con ipotesi sbagliate sulla dimensione di ints/puntatori, sarà molto più fragile e dovrà essere modificato per essere non dipendente dall'architettura.
Molto spesso i file binari contenenti record binari causano più problemi. Ciò è particolarmente vero negli ambienti in cui gli interi crescono da 32 a 64 bit nella transizione a una build a 64 bit. Principalmente ciò è dovuto al fatto che gli interi vengono scritti in modo nativo sui file nella loro lunghezza corrente (32 bit) e letti usando una lunghezza errata in una build a 64 bit dove gli inte sono 64-bit.
Dipende ovviamente dal compilatore, ma tutti i compilatori a 64 bit C che ho usato (gcc, clang), lasciano 'int' a 32 bit e rendono' long' 64 bit. – JeremyP
@JeremyP: dipende dal modello di dati della piattaforma (http://en.wikipedia.org/wiki/64-bit#Specific_C-language_data_models) anziché dal compilatore. Ad esempio su Win64 sia 'int' che' long' rimangono a 32 bit, mentre 'long long' è a 64 bit, quindi il modello è identico a Win32 per gli interi, ma i puntatori diventano 64 bit, quindi il codice che tenta di usare un' int' o 'long' per mantenere un valore del puntatore fallirà - cambiare in' intptr_t' dove richiesto. – Clifford
+1 Solo alcune aggiunte: un brutto caso per argomenti interi sono funzioni va_arg: tutti i tipi interi ristretti che corrispondono al '...' saranno promossi a 'int'. Quindi, il codice che usa il numero intero 'typeof's con la semantica corretta come' size_t', 'uintptr_t',' ptrdiff_t', 'uint64_t' di solito viene compilato ed eseguito. Il codice che ha abusato di 'int' ovunque come variabili di ciclo, non accetta l'aritmetica' char' che potrebbe essere firmata o non firmata, e cose del genere sono alla ricerca di guai. Esegui il tuo codice attraverso diversi compilatori con tutti gli avvisi su, 'clang' è un buon complemento a' gcc' –
@Jens: grazie per i commenti aggiuntivi - il punto su come costruire e testare con più compilatori è molto buono. –