Примечание: Я считаю, что самый эффективный ответ - Serge's answer, но не самый простой для повторного использования. Таким образом, этот ответ ориентирован прежде всего на то, чтобы быть общим, чтобы его можно было повторно использовать с массивами любого размера (при условии, что массив назначения достаточно велик).
Вы также могли бы пройти каждое значение через std::bitset
, что позволит вам сделать более общий вариант.
template<typename FromT, size_t FromSZ, typename ToT, size_t ToSZ>
void convert_to_bits(const FromT (&from_arr)[FromSZ], ToT (&to_arr)[ToSZ]) {
static_assert(ToSZ >= ((sizeof(FromT) * CHAR_BIT) * FromSZ),
"Destination array must have enough elements to contain all bits of source array.");
// Helper value, will be optimised out.
constexpr size_t ELEMENT_SIZE = sizeof(FromT) * CHAR_BIT;
// Handles bit manipulation cleanly.
std::bitset<ELEMENT_SIZE> temp[FromSZ];
// Populate temp.
for (size_t i = 0; i < FromSZ; i++) { temp[i] = from_arr[i]; }
// Fill destination array, one "row" (value in source array) at a time.
for (size_t i = 0; i < FromSZ; i++) {
size_t row = i * ELEMENT_SIZE;
using std::fill;
if (temp[i].none()) {
// Row is all 0s, fill its part of destination array appropriately.
fill(&to_arr[row], &to_arr[row + (ELEMENT_SIZE - 1)], 0);
} else if (temp[i].all()) {
// Row is all 1s, fill its part of destination array appropriately.
fill(&to_arr[row], &to_arr[row + (ELEMENT_SIZE - 1)], 1);
} else {
// Row is mixed, do it one bit at a time.
for (size_t j = 0; j < ELEMENT_SIZE; j++) {
to_arr[row + j] = temp[i][j];
}
}
}
}
Он может быть использован как:
int Data[8] = {0,0,190,42,0,0,2,33};
int bits[8 * (sizeof(int) * CHAR_BIT)] = {0};
convert_to_bits(Data, bits);
Живой пример here.
Это, однако, как правило, будет немного медленнее, чем Serge Ballesta's answer. Чтобы проверить это, я проверил его с this program, составленный в пять раз с каждой из пяти версий макросов:
[Примечание: Все версии по сравнению жестко закодированы такие, что ELEMENT_SIZE == 8
, так что мой код даст эквивалентные результаты для Serge ответ, позволяя мне просто подключить его ответ напрямую. static_assert
удаляется из convert_to_bits()
для размещения этого.]
Каждый случай был собран в отдельную программу, чтобы (надеюсь) свести к минимуму кэширование, и запустить 5 раз в TutorialsPoint's online environment . Параметры оптимизации не заданы.
Один раз с -DSERGE
, для ответа Сержа.
sh-4.3$ g++ -DSERGE main.cpp -std=c++14 -o serge
После того, как с -DTHROUGH
для convert_to_bits()
«s стандартного использования.
sh-4.3$ g++ -DTHROUGH main.cpp -std=c++14 -o through
После того, как с -DDIRECT
, для вручную встраиваемой версии convert_to_bits()
.
sh-4.3$ g++ -DDIRECT main.cpp -std=c++14 -o direct
После того, как с -DFASTDIRECT
, для того, что должно (но не может быть) более эффективным вручную встраиваемой версии.
sh-4.3$ g++ -DFASTDIRECT main.cpp -std=c++14 -o fastdirect
После того, как с -DNAIVE
для наивной версии, которая не использует std::fill()
при необходимости.
sh-4.3$ g++ -DNAIVE main.cpp -std=c++14 -o naive
В среднем ...
serge
взял 29,4 тиков.
through
взял 30,8 клещей.
direct
взял 30,6 клещей.
fastdirect
взял 32,8 клещей.
naive
взял 32,4 клещей.
1: Из-за их связи C++ не работает для меня прямо сейчас, я технически использовал их онлайновую среду Java. Однако это не проблема, так как в среде C++ и Java используется одна и та же песочница с теми же инструментами; единственные отличия, которые я заметил, - это 1), по которым предоставляется программа «Hello World» (файлы можно свободно создавать и переименовывать), и 2) какую команду нажимают кнопки «Скомпилировать» и «Выполнить» (которые могут быть изменено в меню). В обеих средах доступны GCC и Javac, что позволяет легко выполнять их из оболочки Bash.
'j + i', подумайте об этом на мгновение или запустите его шаг за шагом в своем отладчике и подумайте ... –
@SamiKuhmonen Правильно, куча перезаписи происходит. – Jcan1995
Обратите внимание, что если вы хотите, чтобы каждое целое число составляло 8 бит, это помогло бы использовать 'std :: int8_t' вместо' int' (или, если ваш код, возможно, потребуется портировать на платформы, которые не поддерживают 8-битные типы, 'std :: int_least8_t'). Если вы специально хотите целые числа, 'bits' должно быть, вероятно,' sizeof (Data) * CHAR_BIT'. В противном случае вы можете потерять данные. –