Byte puntatore precisione aritmetica in C quando sizeof (char)! = 1
-
16-09-2019 - |
Domanda
Come si può portabile eseguire l'aritmetica dei puntatori con precisione singola byte?
Tenga presente che:
-
char
non è 1 byte su tutte le piattaforme -
sizeof(void) == 1
è disponibile solo come estensione in GCC - Anche se alcune piattaforme possono avere puntatore deref restrizioni di allineamento puntatore, l'aritmetica possono ancora bisogno di una granularità più fine rispetto alla dimensione del più piccolo tipo POD fondamentale
Soluzione
La tua ipotesi è difettoso - sizeof(char)
è definiti per essere 1 in tutto il mondo
C99 standard (TC3) , nella sezione 6.5.3.4 ( "L'operatore sizeof"):
(paragrafo 2)
L'operatore sizeof produce la dimensione (In byte) del suo operando, che può essere un'espressione o la nome tra parentesi di un tipo.
(paragrafo 3)
Quando viene applicato a un operando che ha tipo char, unsigned char, o firmati char, (o una versione qualificato esso) il risultato è 1.
Quando questi sono presi insieme, diventa chiaro che in C, qualsiasi dimensione un char è che la dimensione è un "byte" (anche se è più di 8 bit, in un dato piattaforma).
A char
è quindi del tipo indirizzabile più piccola. Se è necessario affrontare in unità più piccole di una char
, l'unica scelta è quella di leggere un char
alla volta e utilizzare gli operatori bit a bit per mascherare le parti del char
che si desidera.
Altri suggerimenti
Secondo il char
di serie è il più piccolo pezzo indirizzabile di dati. Non ci si può affrontare con maggiore precisione -. Si avrebbe bisogno di fare imballaggio / disimballaggio manualmente
sizeof(char)
è garantito per essere 1
dallo standard C. Anche se char
utilizza 9 bit o più.
Così si può fare:
type *pt;
unsigned char *pc = (unsigned char *)pt;
E utilizzare pc
per l'aritmetica. Assegnazione pc
a pt
utilizzando il cast sopra è un comportamento indefinito dallo standard C però.
Se char
è larga più di 8-bit, non si può fare di byte precisione aritmetica dei puntatori a portatili (ANSI / ISO) C. Qui, da byte , voglio dire 8 bit. Questo perché il tipo fondamentale stessa è più grande di 8 bit.
Cast il puntatore in una uintptr_t
. Questo sarà un numero intero senza segno che è la dimensione di un puntatore. Ora fare il vostro aritmetica su di esso, poi gettato il risultato di nuovo a un puntatore del tipo che si desidera dereference.
(Si noti che intptr_t
è firmato, che di solito non è ciò che si vuole! E 'più sicuro di attenersi a uintptr_t
meno che non abbiate una buona ragione per non!)
Non capisco che cosa si sta cercando di dire con sizeof(void)
essendo 1 in GCC. Mentre il tipo char
potrebbe teoricamente consistere di più di 1 byte macchina sottostante, in linguaggio C sizeof(char)
è 1 e sempre esattamente 1. In altre parole, dal punto di vista del linguaggio C, char
è sempre 1 "byte" (C-byte, non machine byte). Una volta capito questo, si sarebbe anche capire che sizeof(void)
essendo 1 in GCC non vi aiutare in qualsiasi modo. Nel GCC aritmetica puntatore puntatori void *
funziona esattamente allo stesso modo in cui l'aritmetica dei puntatori a puntatori char *
, il che significa che, se su qualche piattaforma char *
non funziona per voi, allora void *
non funzionerà neanche per te.
Se su qualche piattaforma oggetti char
costituiti da più byte macchina, l'unico modo per accedere piccole unità di memoria di un oggetto char
completo sarebbe usare operazioni bit per bit a "estrarre" e "modifica" le porzioni richieste di un char
completo oggetto. linguaggio C non offre alcun modo di affrontare direttamente qualsiasi cosa più piccolo di char
. Ancora una volta char
è sempre un C-byte.
Lo standard C99 definisce l'uint8_t che è di un byte. Se il compilatore non supporta questo tipo, è possibile definire utilizzando un typedef. Naturalmente si avrebbe bisogno di una definizione diversa, a seconda della piattaforma e / o compilatore. Bundle tutto in un file di intestazione e usarlo ovunque.