Conversion d’un tableau d’octets C en un long long

J’ai un tableau de 8 octets dans mon application avec ces données:

00000133339e36a2 

Ces données représentent un long (sur la plate-forme où les données ont été écrites, sur un Mac, ce serait un long long) avec la valeur de

 1319420966562 

Dans l’application réelle, il s’agit d’un dataset semi-aléatoire, de sorte que le nombre sera toujours différent. Par conséquent, j’ai besoin de convertir le tableau d’octets en une longue imprimable.

J’ai essayé de transformer les données directement en un long long, mais je suis venu avec

 1305392 

où j’aurais dû voir le nombre ci-dessus.

Pour ceux d’entre vous qui ont plus d’expérience dans la manipulation d’octets C que moi, comment convertir correctement un tableau d’octets en un long long?

EDIT: Étrangement, toutes vos solutions continuent à générer le même nombre: 866006690. Il s’agit de l’équivalent décimal des quatre derniers octets des données.

Cela semble être l’une des (rares) situations où une union est utile:

 union number { char charNum[16]; long long longNum; }; 
 union le_long_long_array_u { uint8_t byte[8]; uint64_t longlong; } le_long_long_array; 

Copiez (ou utilisez simplement) le_long_long_array.byte[] pour le tableau; relire le_long_long_array.longlong

Par exemple:

 fill_array(&le_long_long_array.byte[0]); return le_long_long_array.longlong; 

Exemple plus complet:

 #include  #include  union le_long_long_array_u { uint8_t byte[8]; uint64_t longlong; } le_long_long_array; static uint8_t hex2int (char c) { return (c >= '0' && c <= '9') ? (uint8_t )(c - '0') : ((c >= 'a' && c <= 'f') ? (uint8_t )(c - 'a') : ((c >= 'A' && c <= 'F') ? (uint8_t )(c - 'A') : 0)); } int main (int argc, char **argv) { if (argc == 2) { int i; for (i = 0; i <= 7; i++) { char *str = argv[1]; if (str[2*i] == '\0' || str[2*i+1] == '\0') { printf("Got short string.\n"); return 1; } le_long_long_array.byte[i] = (hex2int(str[2*i]) << 4) + hex2int(str[2*i+1]); } printf("Got %lld\n", le_long_long_array.longlong); } else { printf("Got %d args wanted 1.\n", argc - 1); return 1; } return 0; } 

Produit:

 ee$ gcc -c un.c ee$ gcc -o un un.o ee$ ./un 0100000000000000 Got 1 ee$ ./un 0101000000000000 Got 257 ee$ ./un a23639333301000000 Got 1319414347266 ee$ 

comme on peut s'y attendre pour les données little endian.

En fonction de votre endianité désirée, quelque chose comme ceci fonctionnerait:

 int i; char inArray[8] = { 0x00,0x00,0x01,0x33,0x33,0x9e,0x36,0xa2 }; long long outLong = 0; for(i=0; i<8; i++) outLong |= ( (long long)inArray[i]) << (i*8) ); 
 long long num = 0; for(int i = 0; i < 8; i++) { num = (num << 8) | byte_array[i]; } 

En supposant qu'ils soient stockés big-endian.

Bonne question! Et de bonnes réponses! Pour verser un centime:

 // Getting stuff "in" unsigned long long ll1 = 1319420966562; unsigned char * c = reinterpret_cast( &ll1 ); // Getting stuff "out" unsigned long long ll2; memcpy( &ll2, c, 8 ); 

ll2 est maintenant égal à ll1 .

Je dois administrer, cependant, j’aime mieux les exemples union . 🙂

Peut-être une notation de pointeur?

 uint8_t Array[8] = { 0x00,0x00,0x01,0x33,0x33,0x9e,0x36,0xa2 }; uint32_t *Long = Array; 

Ou si possible

 *((uint32_t*)Array)