2011-01-24 36 views
6

Tengo una matriz de caracteres sin signo con 2 elementos que representa un número entero con signo. ¿Cómo puedo convertir estos 2 bytes en un entero con signo?Conversión de caracteres sin signo a entero con signo

Editar: La matriz de caracteres sin signo es en Little Endian

+0

Tienes que mirar hacia fuera para endianness , consulte http://en.wikipedia.org/wiki/Endianness –

+0

Hay dos formas en que dos 'char sin signo' podrían representar un entero con signo. Deberías ser más específico sobre eso. –

Respuesta

6

Para mayor seguridad, utilice

int i = *(signed char *)(&c[0]); 
i *= 1 << CHAR_BIT; 
i |= c[1]; 

para big endian. Intercambie c[0] y c[1] por little endian.

(Explicación: interpretamos el byte en c[0] como signed char, a continuación, aritméticamente desplazamiento izquierda de una manera portátil, a continuación, añadir en c[1].)

+0

Como te dije después, si solo lanzas el carácter sin signo al carácter firmado, corres el riesgo de que se expanda el signo. Mejor enmascare el resultado con 0x0000FFFF para asegurarse de que el bit de signo sea bajo. –

+0

@ Mr.Gate, no estoy "simplemente" lanzando 'char sin signo' a' firmado char'. Estoy usando un molde de puntero para reinterpretar el patrón de bits como 'signed char', luego promover a' int'. –

+1

La mayoría de los compiladores ** no ignoran ** las reglas de aliasing. GCC seguramente generará código que no hará lo que usted desea a menos que usted le pase opciones especiales. –

2

Se dependen del orden de bits. Algo para big endian:

unsigned char x[2]; 
short y = (x[0] << 8) | x[1] 

Algo para Little Endian:

unsigned char x[2]; 
short y = (x[1] << 8) | x[0] 
+1

* unsigned * chars ... –

+0

Esto no es probable que funcione en muchos sistemas, particularmente cuando plain 'char' está firmado (' x [0] 'y' x [1] 'tendrán extensión de signo, por lo que si el menos significativo es negativo, el byte superior se establecerá en todos los 1 por el OR de bit a bit). – caf

5

envolverlos en una unión:

union { 
    unsigned char a[2]; 
    int16_t smt; 
} number; 

Ahora después de llenar la matriz se puede utilizar esto como number.smt

+2

@VGE: la conversión 'short' a' int' está bien definida. Aunque recomendaría usar 'int16_t' en lugar de' short'. –

1

La solución portátil:

unsigned char c[2]; 
long tmp; 
int result; 

tmp = (long)c[0] << 8 | c[1]; 
if (tmp < 32768) 
    result = tmp; 
else 
    result = tmp - 65536; 

Esto supone que los bytes en la matriz representan un entero con signo de 16 bit, complemento de dos, big endian. Si son un entero pequeño endian, simplemente intercambie c[1] y c[0].

(En el caso muy improbable de que es complemento a uno, utilice 65535 en lugar de 65536 como el valor a restar sesión de magnitud se deja como ejercicio para el lector;).

+0

Prefiero enmascarar el resultado con 0x0000FFFF.Esto garantiza que, incluso si el bit de signo se expandió, otorgará el valor dentro de 0x0000FFFF y 0. –

+0

@ Mr.Gate: no es necesario ningún tipo de enmascaramiento. Como 'c [0]' y 'c [1]' son números positivos entre 0 y 255, 'tmp' es un número positivo en el rango 0 a 65535. El único número negativo se produce en la resta final - no hay posibilidad de extensión de signo no deseado. – caf

Cuestiones relacionadas