Byte aritmética de punteros precisión en C cuando sizeof (char)! = 1
-
16-09-2019 - |
Pregunta
¿Cómo se puede realizar de forma portátil aritmética de punteros con la precisión de un solo byte?
Tenga en cuenta que:
-
char
no es de 1 byte en todas las plataformas -
sizeof(void) == 1
sólo está disponible como una extensión de GCC - Si bien algunas plataformas pueden tener puntero DEREF restricciones de alineación de punta, la aritmética todavía pueden requerir una granularidad más fina que el tamaño del tipo POD fundamental más pequeño
Solución
Su suposición es errónea - sizeof(char)
es definido a ser de 1 en todas partes
Desde el C99 estándar (TC3) , en la sección 6.5.3.4 ( "El operador sizeof"):
(párrafo 2)
El operador sizeof produce el tamaño (En bytes) de su operando, que puede ser una expresión o la nombre entre paréntesis de un tipo.
(párrafo 3)
Cuando se aplica a un operando que tiene tipo char, unsigned char, o firmado char, (o una versión calificada de la misma) el resultado es 1.
Cuando éstas se toman en conjunto, se hace evidente que en C, sea cual sea el tamaño de un char es, que el tamaño es un "byte" (incluso si eso es más de 8 bits, en alguna plataforma dada).
A char
por lo tanto, es el tipo direccionable más pequeño. Si usted necesita para hacer frente en unidades más pequeñas que un char
, su única opción es leer una char
a la vez y utilizar operadores de bits para enmascarar las partes de la char
que desee.
Otros consejos
De acuerdo con la char
estándar es el trozo direccionable más pequeña de datos. Usted simplemente no puede hacer frente con mayor precisión -. Lo que tendría que hacer el embalaje / desembalaje manualmente
sizeof(char)
se garantiza que se 1
por la norma C. Incluso si utiliza char
9 bits o más.
Por lo que puede hacer:
type *pt;
unsigned char *pc = (unsigned char *)pt;
Y el uso de pc
para la aritmética. Asignar a pc
pt
utilizando el elenco anterior es un comportamiento no definido por la norma C embargo.
Si char
es más de 8 bits de ancho, no se puede hacer bytes precisión aritmética de punteros en el portátil (ANSI / ISO) C. En este caso, por bytes , me refiero a 8 bits. Esto se debe a que el propio tipo fundamental es mayor que 8 bits.
Reparto el puntero a una uintptr_t
. Este será un entero sin signo que es el tamaño de un puntero. Ahora haga su aritmética en él, a continuación, emitir el resultado de nuevo a un puntero del tipo que desea eliminar la referencia.
(Tenga en cuenta que intptr_t
está firmado, que por lo general no es lo que quiere! Es más seguro que se adhieren a uintptr_t
a menos que tenga una buena razón para no hacerlo!)
No entiendo lo que está intentando decir con sizeof(void)
siendo 1 en GCC. Mientras que el tipo char
teóricamente podría consistir en más de 1 byte de la máquina subyacente, en C sizeof(char)
lenguaje es 1 y siempre exactamente 1. En otras palabras, desde el punto de vista del lenguaje C, char
es siempre 1 "byte" (C-byte, no byte de la máquina). Una vez que entienda esto, también se entendería que sizeof(void)
siendo 1 en GCC no le ayuda de alguna manera. En GCC la aritmética de punteros sobre punteros void *
funciona exactamente de la misma manera que en la aritmética de punteros punteros char *
, lo que significa que si en alguna char *
plataforma no funciona para usted, entonces void *
no va a funcionar para usted tampoco.
Si en alguna plataforma objetos char
consisten en múltiples bytes de la máquina, la única manera de acceder a unidades más pequeñas de memoria de la que un objeto char
completo sería utilizar operaciones bit a bit a "extraer" y "modificar" las porciones requeridas de un char
completa objeto. lenguaje C no ofrece ninguna manera de abordar directamente algo más pequeño que char
. Una vez más char
siempre es un C-byte.
El estándar C99 define el uint8_t que es de un byte de largo. Si el compilador no admite este tipo, se podría definir usando un typedef. Por supuesto que se necesita una definición diferente, dependiendo de la plataforma y / o compilador. Empaquetar todo en un archivo de cabecera y usarlo en todas partes.