I am trying to stuff 16 unsigned values into 8 bytes (64 bit), and access them using an array-like syntax.
Every entry in the "array" will be one nibble - 4 bit long. (The values I plan to store are never bigger than 15).
My first attempt was this:
int main(int argc, char* argv[]) {
union nibbles_array {
uint64_t as_long;
struct inner_array {
unsigned entry0 : 4;
unsigned entry1 : 4;
unsigned entry2 : 4;
unsigned entry3 : 4;
unsigned entry4 : 4;
unsigned entry5 : 4;
unsigned entry6 : 4;
unsigned entry7 : 4;
unsigned entry8 : 4;
unsigned entry9 : 4;
unsigned entry10 : 4;
unsigned entry11 : 4;
unsigned entry12 : 4;
unsigned entry13 : 4;
unsigned entry14 : 4;
unsigned entry15 : 4;
} as_array;
} array;
array.as_long = 0x0123456789abcdef;
printf("%d \n", array.as_array.entry0);
printf("%d \n", array.as_array.entry1);
printf("%d \n", array.as_array.entry2);
printf("%d \n", array.as_array.entry3);
printf("%d \n", array.as_array.entry4);
return 0;
}
Two problems arises from this implementation: the first is that the values are stored in reverse order. I can, of course, assign the values in reverse order to get the desired result: array.as_long = 0xfedcba9876543210
, but I want this code to be portable, and not endianness-dependent.
The second is that I can't access the nibbles with an index, in an array-like syntax.
The second attempt was this:
int main(int argc, char* argv[]) {
uint64_t pseudo_array = 0x0123456789abcdef;
#define Array(i) (unsigned)((pseudo_array & (0xfUL << i)) >> i)
int i;
for (i = 0; i < 16; ++i) {
printf("%d ", Array(i));
}
printf("\n");
return 0;
}
The above can solve the second problem (array-like syntax); now I can access "elements" with index, but the problem of endianness remains, plus this produces wrong output:
15 7 11 13 14 15 7 11 13 6 3 9 12 14 15 7
- Why is the above produces this output?
- Can you please suggest implementation that will both allow me to access the "array" by index and will solve the endianness problem?