Преобразование массива байтов C в long long - PullRequest
5 голосов
/ 24 октября 2011

У меня есть 8-байтовый массив в моем приложении с этими данными:

00000133339e36a2

Эти данные представляют собой длинные данные (на платформе, в которую были записаны данные, на Mac это будет длинный) со значением

1319420966562

В реальном приложении это полурандомизированный набор данных, поэтому число всегда будет другим.Поэтому мне нужно преобразовать байтовый массив в длинный длинный для печати. ​​

Я пытался преобразовать данные напрямую в длинный длинный, но я придумал

1305392

, где ядолжен был видеть вышеуказанное число.

Для тех из вас, кто имеет больший опыт работы с байтами C, чем я, как бы я правильно преобразовал байтовый массив в long long?

EDIT:Как ни странно, все ваши решения продолжают выводить одно и то же число: 866006690. Это десятичный эквивалент последних четырех байтов данных.

Ответы [ 6 ]

3 голосов
/ 24 октября 2011
union le_long_long_array_u
{
  uint8_t byte[8];
  uint64_t longlong;
} le_long_long_array;

Копировать (или просто использовать) le_long_long_array.byte[] для массива;чтение назад le_long_long_array.longlong

Например:

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

Более полный пример:

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

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;
}

Производит:

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

, как и следовало ожидатьдля данных с прямым порядком байтов.

3 голосов
/ 24 октября 2011

Это кажется одной из (редких) ситуаций, когда объединение полезно:

union number
{
    char charNum[16];
    long long longNum;
};
2 голосов
/ 24 октября 2011

В зависимости от желаемого порядка байтов, что-то вроде этого будет работать:

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) );
1 голос
/ 24 октября 2011

Отличный вопрос!И отличные ответы!Чтобы добавить цент:

// Getting stuff "in"
unsigned long long ll1 = 1319420966562;
unsigned char * c = reinterpret_cast<unsigned char *>( &ll1 );

// Getting stuff "out"
unsigned long long ll2;
memcpy( &ll2, c, 8 );

ll2 теперь равно ll1.

Я должен быть администратором, однако мне больше нравятся примеры union.:)

1 голос
/ 24 октября 2011
long long num = 0;
for(int i = 0; i < 8; i++) {
    num = (num << 8) | byte_array[i];
}

При условии, что они хранятся в старшем порядке.

0 голосов
/ 24 ноября 2015

Возможно указатель нотации?

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

Или, если возможно

*((uint32_t*)Array)
...