2012-03-14 11 views
11

Tengo problemas para convertir int64_t en una matriz char y viceversa. No sé lo que está mal con el código a continuación, tiene un completo sentido lógico para mí. El código funciona para a como se muestra, pero no para el segundo número b que claramente cae en el rango de int64_t.¿Cómo convierto un entero de 64 bits en una matriz de caracteres y viceversa?

#include <stdio.h> 
#include <stdint.h> 

void int64ToChar(char mesg[], int64_t num) { 
    for(int i = 0; i < 8; i++) mesg[i] = num >> (8-1-i)*8; 
} 

int64_t charTo64bitNum(char a[]) { 
    int64_t n = 0; 
    n = ((a[0] << 56) & 0xFF00000000000000U) 
    | ((a[1] << 48) & 0x00FF000000000000U) 
    | ((a[2] << 40) & 0x0000FF0000000000U) 
    | ((a[3] << 32) & 0x000000FF00000000U) 
    | ((a[4] << 24) & 0x00000000FF000000U) 
    | ((a[5] << 16) & 0x0000000000FF0000U) 
    | ((a[6] << 8) & 0x000000000000FF00U) 
    | (a[7]  & 0x00000000000000FFU); 
    return n; 
} 

int main(int argc, char *argv[]) { 
    int64_t a = 123456789; 
    char *aStr = new char[8]; 
    int64ToChar(aStr, a); 
    int64_t aNum = charTo64bitNum(aStr); 
    printf("aNum = %lld\n",aNum); 

    int64_t b = 51544720029426255; 
    char *bStr = new char[8]; 
    int64ToChar(bStr, b); 
    int64_t bNum = charTo64bitNum(bStr); 
    printf("bNum = %lld\n",bNum); 
    return 0; 
} 

salida es

aNum = 123456789 
bNum = 71777215744221775 

El código también da dos advertencias de que no sé cómo deshacerse de él.

warning: integer constant is too large for ‘unsigned long’ type 
warning: left shift count >= width of type 
+3

la segunda advertencia es la clave. Los operandos de '<<' se promocionan a 'int', por lo que' a [0] << 56' será siempre 0. Pruebe '((int64_t) a [0])' etc. La primera advertencia es sobre 51544720029426255 , debe decir 51544720029426255LL. –

+0

http://ideone.com/dKIWT – aroth

Respuesta

7

Esto es muy sencillo, el problema es que usted está cambiando bits en la matriz de caracteres, pero el tamaño de a[i] es 4 byes (upcast a int), por lo que su turno va más allá del rango. Trate de reemplazar esto en su código:

int64_t charTo64bitNum(char a[]) { 
    int64_t n = 0; 
    n = (((int64_t)a[0] << 56) & 0xFF00000000000000U) 
    | (((int64_t)a[1] << 48) & 0x00FF000000000000U) 
    | (((int64_t)a[2] << 40) & 0x0000FF0000000000U) 
    | (((int64_t)a[3] << 32) & 0x000000FF00000000U) 
    | ((a[4] << 24) & 0x00000000FF000000U) 
    | ((a[5] << 16) & 0x0000000000FF0000U) 
    | ((a[6] << 8) & 0x000000000000FF00U) 
    | (a[7]  & 0x00000000000000FFU); 
    return n; 
} 

De esta forma podrás emitir el char a un número de 64 bits antes de hacer el cambio y no va a salir en todo el rango. Usted va a obtener resultados correctos:

entity:Dev jack$ ./a.out 
aNum = 123456789 
bNum = 51544720029426255 

Sólo una nota, creo que esto funcionaría bien también, asumiendo que no hay que mirar dentro de la matriz de caracteres:

#include <string.h> 

void int64ToChar(char a[], int64_t n) { 
    memcpy(a, &n, 8); 
} 

int64_t charTo64bitNum(char a[]) { 
    int64_t n = 0; 
    memcpy(&n, a, 8); 
    return n; 
} 
+0

Preferiría su alternativa, memcpy a la variable int64_t directamente, pero no creo que funcione, por ejemplo: char * szInput = "51544720029426255";/* 17 bytes, más de 8 bytes */ memcpy (& n, szInput, 8); dará lugar a un desbordamiento, ¿no crees? Gracias – Zennichimaro

+0

No, porque está especificando que copiará solo 8 bytes en cualquier caso a través del tercer parámetro. – Jack

+1

oh ya ... pero solo copiará los primeros 8 bytes, cout << n; se imprimirá: 51544720, ¿verdad? 51544720029426255 debe mantenerse en int64_t ya que el valor máximo que puede contener es 9223372036854775807. – Zennichimaro

0

En charTo64bitNum se que tenga que emitir el char a 64 bits antes de cambiar que:

(((int64_t)a[0] << 56) & 0xFF00000000000000U) 
1
void int64ToChar(char mesg[], int64_t num) { 
    *(int64_t *)mesg = num; //or *(int64_t *)mesg = htonl(num); 

} 
Cuestiones relacionadas