Как преобразовать массив байтов в UInt64 в Objective-C

Это то, что я сделал, чтобы преобразовать 8 байтов, которые я получил, в UInt64:

+ (UInt64)convertByteArrayToUInt64:(unsigned char *)bytes ofLength:(NSInteger)length
{
    UInt64 data = 0;

    for (int i = 0; i < length; i++)
    {
        data = data | ((UInt64) (bytes[i] & 0xff) << (24 - i * 8));
    }

    return data;
}

Отправитель, который преобразует данные в 8-байтовые данные, сделал это следующим образом:

for(int i=1;i<9;i++)
{
    statusdata[i] = (time >> 8*i & 0xff);
}

8-байтовые данные, которые я получил:

01 00 00 00 00 00 00 3b

Результат моего метода:

16777216

Я попытался преобразовать это «16777216» в байты с помощью калькулятора и получил:

01 00 00 00 00 00 00

что означает, что 3b не было включено в преобразование.

Но я попробовал этот код под java, и он отлично работает. Я не знаю, где проблема.

Пожалуйста помоги. Заранее спасибо!


person JLT    schedule 16.09.2015    source источник


Ответы (1)


UInt64 составляет 8 байт, поэтому, если у вас есть 8-байтовый буфер, все, что вам нужно сделать, это создать на него указатель UInt64 и разыменовать его (если данные находятся в формате с прямым порядком байтов на архитектурах x86, но я получу к этому через секунду),

So:

unsigned char foo[8] = {0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01};

UInt64 *n = (UInt64 *) foo;  // pointer to value 0x0102030405060708

UInt64 nValue = *n;

Имейте в виду, что отдельные значения байтов на оборудовании x86 имеют прямой порядок следования байтов, поэтому наименее значимый байт идет первым в буфере. Таким образом, если вы думаете о буфере выше как об отдельных цифрах с основанием 16, число будет:

0x0102030405060708 (старший байт в буфере последним).

Хитрость, которую вы ищете, заключается в том, чтобы просто преобразовать ваш 8-байтовый буфер в UInt64* и разыменовать его. Если вы никогда не видели порядок хранения/порядка байтов с прямым и обратным порядком байтов, я рекомендую вам прочитать об этом.

p.s. - Между прочим, код отправителя неверен, индекс массива (i) должен быть от 0 до 7, поэтому (i=0;i<8;++i), не 1-8 или значение time не будет скопировано правильно. Между прочим, отправитель пытается скопировать time в statusdata в порядке с прямым порядком байтов (наименее значащий байт в буфере идет первым), но опять же, это делается неправильно.

Кроме того, если код отправителя находится на Java, вам нужно быть осторожным, чтобы значение time на самом деле не должно было быть отрицательным. В Java нет целочисленных значений без знака, поэтому, если time отрицательное и вы преобразуете его в UInt64, это будет большое положительное значение, а это не то, что вам нужно.

Для полноты картины я покажу вам, как байт за байтом восстановить данные из буфера с прямым порядком байтов, но помните, что код отправителя неверен и должен быть переписан с нулевым индексом (и приведением типа как показано выше, вы также получите это):

data = 0

for (i=0; i < 8; ++i) {
    data = (data << 8) | bytes[i];  // bytes is already UInt8 * so no need to mask it
}
person par    schedule 16.09.2015