Note: I consider Serge's answer to be the most efficient answer, but not the easiest to reuse. As such, this answer is aimed primarily at being generic, so that it can be reused with arrays of any size (providing that the destination array is large enough).
You could also pass each value through a std::bitset, which would allow you to make a more generic version.
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];
}
}
}
}
It can be used as:
int Data[8] = {0,0,190,42,0,0,2,33};
int bits[8 * (sizeof(int) * CHAR_BIT)] = {0};
convert_to_bits(Data, bits);
Live example here.
This, though, will typically be slightly slower than Serge Ballesta's answer. To check this, I tested it with this program, compiled five times with each of the five version macros:
[Note: All versions compared are hard-coded such that ELEMENT_SIZE == 8, so that my code would give equivalent results to Serge's answer, allowing me to just plug his answer in directly. The static_assert is removed from convert_to_bits() to accomodate this.]
Each case was compiled into a separate program, to (hopefully) minimise caching, and run 5 times in TutorialsPoint's online environment1. No optimisation options were specified.
Once with -DSERGE, for Serge's answer.
sh-4.3$ g++ -DSERGE main.cpp -std=c++14 -o serge
Once with -DTHROUGH, for convert_to_bits()'s standard use case.
sh-4.3$ g++ -DTHROUGH main.cpp -std=c++14 -o through
Once with -DDIRECT, for a manually-inlined version of convert_to_bits().
sh-4.3$ g++ -DDIRECT main.cpp -std=c++14 -o direct
Once with -DFASTDIRECT, for what should (but may not be) a more efficient manually-inlined version.
sh-4.3$ g++ -DFASTDIRECT main.cpp -std=c++14 -o fastdirect
Once with -DNAIVE, for a naive version that doesn't use std::fill() when appropriate.
sh-4.3$ g++ -DNAIVE main.cpp -std=c++14 -o naive
On average...
serge took 29.4 ticks.
through took 30.8 ticks.
direct took 30.6 ticks.
fastdirect took 32.8 ticks.
naive took 32.4 ticks.
1: Due to their C++ links not working for me right now, I technically used their online Java environment. This is a non-issue, however, since both their C++ and Java environments use the same sandbox, with the same tools; the only differences I've noticed are 1) which default "Hello World" program is supplied (files can freely be created and renamed), and 2) what command the "Compile" and "Execute" buttons are mapped to (which can be changed in the menu). Both environments have GCC and Javac freely available, allowing for easy execution from the Bash shell.
j+i, think about that for a moment, or run it step by step in your debugger and think...std::int8_tinstead ofint(or, if your code may need to be ported to platforms that don't support 8-bit types,std::int_least8_t). If you specifically want integers,bitsshould probably besizeof(Data) * CHAR_BIT. Otherwise, you could potentially lose data.