2010-12-03 10 views
8

Esto podría ser muy básico o incluso tonto para los expertos aquí, pero quería entender esto. La mayoría de las veces que generalmente escribir valores hexadecimales como esta en C:Interpretando valores hexadecimales?

unsigned int a = 0xFFFF1232; 

Digamos que estoy tratando de extraer los primeros y los últimos 16 bits entonces puedo simplemente hacer:

unsigned short high = a >> 16; // Gives me 0xFFFF 
unsigned short low = a & 0x0000FFFF; // Gives me 0x000which is then stored as 0x1232 

En algunos del código que estoy leyendo me he encontrado lo siguiente:

unsigned short high = a >> 16; 
unsigned short low = a & 0xFFFF; 

tengo dos preguntas

  • Cuando está AND ing un valor de 32 bits con una máscara, ¿por qué las personas escriben 0xFFFF en lugar de 0x0000FFFF? ¿Es para mantenerlo compacto?
  • ¿Es siempre seguro escribir 0x0000FFFF como 0xFFFF? ¿Se interpreta de manera diferente en cualquier contexto?

Respuesta

7

Son completamente sinónimos. Dejar los ceros a la izquierda lo hace un poco más legible.

+0

Creo que uno es "más legible" aquí es discutible y está sujeto a interpretación, pero +1. –

+0

Prefiero decir "menos legible" (por ejemplo: hoy es 00000002010/00000000012/00000000004). – ruslik

+0

@xscott: es perfectamente legal escribir 'char c = 0x000000000000000000001;' recibirá una advertencia solo cuando el valor real (y no su representación) exceda el tamaño del destino, – ruslik

2

En su ejemplo low es un short (normalmente 16 bits). Por lo tanto, los ceros iniciales no solo son redundantes, sino que sugieren que se espera un resultado de 32 bits, y en este caso los bits superiores se descartan, por lo que podría aclarar la intención del código.

De hecho, en este caso

unsigned short low = a ; 

sería suficiente, aunque es tal vez menos claro.

Además no se debe asumir que los anchos enteros son apropiados y utilizar los <stdint.h> tipos vez:

uint32_t a = 0xFFFF1232; 
uint16_t = a >> 16; 
uint16_t = a & 0xFFFF; 

Si está utilizando VC++ que no alimente ese encabezado, puede utilizar this implementation

+0

Sí, pero recuerde que la operación & * se realizará * entre dos entradas, con el resultado siendo degradado a corto. – Roddy

+0

'short low = a' no es portable si short es> 16 bits ... – Roddy

+0

@Roddy: Eso es cierto, pero usar tales tipos para manipular el ancho de bits es una mala idea. Escribiría 'uint16_t bajo = a;' personalmente. En realidad, no lo haría, dejaría la máscara de bits por claridad de intento. – Clifford

3

Ellos Son identicos.

Y, supongo que siempre tienen 32 bits de longitud. Si tu plataforma pasó a usar ints de 64 bits, ¿lo escribirías así?

unsigned short low = a & 0x000000000000FFFF; // ouch. Did I count them right? 

Y hay otra razón por la que no debe perder tiempo en poner en ceros a la izquierda: Vas a tratar de hacer con decimales siguiente, que es una mala idea:

int x = 00000377 

printf("%d\n", x); // 255! WTF.... 
+1

Sí ... lo escribiría de esa manera. Si pone demasiados ceros, no dolerá nada (podría dar una advertencia al compilador). Si incluyes muy pocos, del mismo modo ... pero si tratas de poner el ancho correcto, al menos has intentado documentar lo que crees que está sucediendo aquí. – jkerian

1

Algo así como 0x1 se llama literal, que por defecto es un tipo int. Esto no es necesariamente 32 bits, dependiendo del compilador o plataforma, así que sí, hay un contexto en el que no es seguro dejar los ceros a la izquierda.

Por ejemplo, en los sistemas embebidos, es común encontrar tipos de int que tienen solo 16 bits de longitud. Si quieres un número entero más largo, necesitas usar int largo.

En ese caso, el compilador se dará cuenta si olvidó agregar "L" al literal hexadecimal, para indicar que desea el tipo más largo.

unsigned int a = 0xFFFF1234; 

sería un error de compilación en el mejor, o un error no detectado en el peor. Necesitaría usar

unsigned long int a = 0xFFFF1234L; 

en su lugar.

+0

Los compiladores no notarán los ceros a la izquierda para los literales largos. Verán si el resultado binario se ajusta, no la representación textual – Roddy

1

En su caso, 0x0000FFFF y 0xFFFF son idénticos.

Esto no sería el caso si sus variables no estuvieran sin firmar: un valor de 16 bits de 0xFFFF significa -1, que es 0xFFFFFFFF en 32 bits.

Cuestiones relacionadas