C: работа с массивом символов в виде 8-байтовых блоков - PullRequest
2 голосов
/ 06 октября 2010

У меня есть массив символов и указатель на него.Мне нужно добавить первые 8 байтов (двоичное значение 8 байтов) ко вторым 8 байтов по модулю 2exp (64).Как я мог это сделать?

Я нашел решение.Но делать такие вещи определенно нехорошо (см. Код).Тем не менее было бы неплохо получить результат в массиве chars.

void init(const unsigned char *k) {
    uint64_t *kp = k;
    uint64_t sum = (*kp + *(kp+1)) % pow(2,64)
}

Спасибо за помощь

Ответы [ 3 ]

8 голосов
/ 06 октября 2010

Вам не нужен % pow(2,64), и фактически он вводит ошибки, так как он преобразует результат в double. Арифметика типа uint64_t уже по модулю 2 ^ 64.

Проблема чтения 8 байтов как uint64_t в основном о том, над какими реализациями C вы хотите, чтобы он работал, и о формате 8 байтов в вашем массиве символов.

Если вы знаете, что 8 байтов в массиве char имеют тот же самый порядок байтов, что и ваша система (то есть самый старший байт сначала, если ваша система имеет старший-байтовый цикл, самый старший байт последний, если ваша система имеет младший порядок байтов) ), то, что вы делаете, вероятно, в порядке. Кто бы ни поставлял буфер, он должен убедиться, что он правильно выровнен, хотя, если в вашей системе есть ограничения на uint64_t.

Если данные поступили из какого-либо файла или через Интернет, то порядковый номер может не соответствовать системе и, вероятно, не будет правильно выровнен.

Если 8 байтов с прямым порядком байтов, этот код не будет работать в системе с прямым порядком байтов, поэтому, если вы хотите, чтобы ваш код был переносимым, вам нужно было бы сделать что-то еще. Существуют системы, в которых unit64_t не занимает 8 байт, и даже memcpy не работает. Спецификация вашей функции может означать, что она полностью неприменима к таким системам, но в некоторых случаях имеет смысл преобразовать массив из 8 символов в uint64_t, независимо от того, действительно ли CHAR_BIT больше 8.

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

Как бы вы ни читали данные, если вы хотите получить результат обратно в массив символов, затем выполните обратный процесс - в случае вашего кода *((uint64_t*)output_buffer) = kp[0] + kp[1];.

1 голос
/ 06 октября 2010

Я почти уверен, что 2pow64 по модулю естественным образом получается из точности ваших данных (в данном случае 64 бита)

, поэтому создайте целые 2 переменные, точность 64 бита, без знака.Вызовите a и b.

и переместите первые 4 байта в a, 4 следующих байта в b, добавьте a к b.

Фактически вам просто не нужно делать это по модулю.

0 голосов
/ 06 октября 2010

Проблема в выравнивании.Может случиться так, что указатели на целые числа должны быть правильно выровнены на вашей платформе;надежное решение состоит в том, чтобы просто скопировать ваши байты во временные переменные.

void init(const unsigned char *k) {
    uint64_t a, b; // two local variables 
    memcpy(&a,k,8); // fill them up
    memcpy(&b,k+8,8); // you presumably mean k+8?
    uint64_t sum = a + b;
    // do something with sum
}

Возможно, вам также понадобится рассмотреть порядок байтов;посмотрите на 64-битный ntohl () в C ++?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...