Reversing Endianess C - c

I'm lost on bit shifting operations, I'm trying to reverse byte order on 32 bit ints, what I've managed to look up online I only got this far but cant seem to find why its not working
int32_t swapped = 0; // Assign num to the tmp
for(int i = 0; i < 32; i++)
{
swapped |= num & 1; // putting the set bits of num
swapped >>= 1; //shift the swapped Right side
num <<= 1; //shift the swapped left side
}
And I'm printing like this
num = swapped;
for (size_t i = 0; i < 32; i++)
{
printf("%d",(num >> i));
}

Your code looks likes its attempting to swap bits, and not bytes. If you are wanting to swap bytes, then the 'complete' method would be:
int32_t swapped = ((num >> 24) & 0x000000FF) |
((num >> 8) & 0x0000FF00) |
((num << 8) & 0x00FF0000) |
((num << 24) & 0xFF000000);
I say 'complete', because the last bitwise-and can be omitted, and the first bitwise-and can be omitted if num is unsigned.
If you want to swap the bits in a 32bit number, your loop should probably max out at 16 (if it's 32, the first 16 steps will swap the bits, the next 16 steps will swap them back again).
int32_t swapped = 0;
for(int i = 0; i < 16; ++i)
{
// the masks for the two bits (hi and lo) we will be swapping
// shift a '1' to the correct bit location based on the index 'i'
uint32_t hi_mask = 1 << (31 - i);
uint32_t lo_mask = 1 << i;
// use bitwise and to mask out the original bits in the number
uint32_t hi_bit = num & hi_mask;
uint32_t lo_bit = num & lo_mask;
// shift the bits so they switch places
uint32_t new_lo_bit = hi_bit >> (31 - i);
uint32_t new_hi_bit = lo_bit << (31 - i);
// use bitwise-or to combine back into an int
swapped |= new_lo_bit;
swapped |= new_hi_bit;
}
Code written for readability - there are faster ways to reverse the bits in a 32bit number. As for printing:
for (size_t i = 0; i < 32; i++)
{
bool bit = (num >> (31 - i)) & 0x1;
printf(bit ? "1" : "0");
}

Related

Effective bits calculation along the array in specified position on STM32

I'm wondering if someone know effective approach to calculate bits in specified position along array?
Assuming that OP wants to count active bits
size_t countbits(uint8_t *array, int pos, size_t size)
{
uint8_t mask = 1 << pos;
uint32_t result = 0;
while(size--)
{
result += *array++ & mask;
}
return result >> pos;
}
You can just loop the array values and test for the bits with a bitwise and operator, like so:
int arr[] = {1,2,3,4,5};
// 1 - 001
// 2 - 010
// 3 - 011
// 4 - 100
// 5 - 101
int i, bitcount = 0;
for (i = 0; i < 5; ++i){
if (arr[i] & (1 << 2)){ //testing and counting the 3rd bit
bitcount++;
}
}
printf("%d", bitcount); //2
Note that i opted for 1 << 2 which tests for the 3rd bit from the right or the third least significant bit just to be easier to show. Now bitCount would now hold 2 which are the number of 3rd bits set to 1.
Take a look at the result in Ideone
In your case you would need to check for the 5th bit which can be represented as:
1 << 4
0x10000
16
And the 8th bit:
1 << 7
0x10000000
256
So adjusting this to your bits would give you:
int i, bitcount8 = 0, bitcount5 = 0;
for (i = 0; i < your_array_size_here; ++i){
if (arr[i] & 0x10000000){
bitcount8++;
}
if (arr[i] & 0x10000){
bitcount5++;
}
}
If you need to count many of them, then this solution isn't great and you'd be better off creating an array of bit counts, and calculating them with another for loop:
int i, j, bitcounts[8] = {0};
for (i = 0; i < your_array_size_here; ++i){
for (j = 0; j < 8; ++j){
//j will be catching each bit with the increasing shift lefts
if (arr[i] & (1 << j)){
bitcounts[j]++;
}
}
}
And in this case you would access the bit counts by their index:
printf("%d", bitcounts[2]); //2
Check this solution in Ideone as well
Let the bit position difference (e.g. 7 - 4 in this case) be diff.
If 2diff > n, then code can add both bits at the same time.
void count(const uint8_t *Array, size_t n, int *bit7sum, int *bit4sum) {
unsigned sum = 0;
unsigned mask = 0x90;
while (n > 0) {
n--;
sum += Array[n] & mask;
}
*bit7sum = sum >> 7;
*bit4sum = (sum >> 4) & 0x07;
}
If the processor has a fast multiply and n is still not too large, like n < pow(2,14) in this case. (Or n < pow(2,8) in the general case)
void count2(const uint8_t *Array, size_t n, int *bit7sum, int *bit4sum) {
// assume 32 bit or wider unsigned
unsigned sum = 0;
unsigned mask1 = 0x90;
unsigned m = 1 + (1u << 11); // to move bit 7 to the bit 18 place
unsigned mask2 = (1u << 18) | (1u << 4);
while (n > 0) {
n--;
sum += ((Array[n] & mask1)*m) & mask2;
}
*bit7sum = sum >> 18;
*bit4sum = ((1u << 18) - 1) & sum) >> 4);
}
Algorithm: code is using a mask, multiply, mask to separate the 2 bits. The lower bit remains in it low position while the upper bit is shifted to the upper bits. Then a parallel add occurs.
The loop avoids any branching aside from the loop itself. This can make for fast code. YMMV.
With even larger n, break it down into multiple calls to count2()

promoting integer to long or unsigned long

static uint32_t get_num(void);
uint32_t get_count(unsigned int mask)
{
uint8_t i = 0;
uint32_t count = 0;
while (i < get_num())
{
if (mask & (1 << i++))
count++;
}
return count;
}
In this code, what would be more safe (1L << i++) or (1UL << i++) ?
An unsigned operand is a bit safer because only then is the behavior of all the shifts defined when get_num() returns the number of bits in that operand's type. If unsigned long is wider than unsigned int then UL is slightly safer than just U, but only for accommodating get_num() results that aren't valid anyway.
Safer yet, however, is this:
uint32_t get_count(uint32_t mask)
{
uint8_t num = get_num();
if (num == 0) return 0;
/* mask off the bits we don't want to count */
mask &= ~((uint32_t) 0) >> ((num < 32) ? (32 - num) : 0);
/* count the remaining 1 bits in mask, leaving the result in mask */
mask = (mask & 0x55555555) + ((mask & 0xaaaaaaaa) >> 1);
mask = (mask & 0x33333333) + ((mask & 0xcccccccc) >> 2);
mask = (mask & 0x0f0f0f0f) + ((mask & 0xf0f0f0f0) >> 4);
mask = (mask & 0x00ff00ff) + ((mask & 0xff00ff00) >> 8);
mask = (mask & 0x0000ffff) + ((mask & 0xffff0000) >> 16);
return mask;
}
If you just want to count the 1-bits in an uint and use gcc, you should have a look at the builtin functions (here: int __builtin_popcount (unsigned int x)). These can be expected to be highly optimized and even use special instructions of the CPU where available. (one could very wenn test for gcc).
However, not sure what get_num() would yield - it just seems not to depend on mask, so its output can be used to limit the result of popcount.
The following uses a loop and might be faster than a parallel-add tree on some architectures (one should profile both versions if timing is essential).
unsigned popcount(uint32_t value, unsigned width)
{
unsigned cnt = 0; // actual size intentionally by arch
if ( width < 32 )
value &= (1UL << width) - 1; // limit to actual width
for ( ; value ; value >>= 1 ) {
cnt += value & 1U; // avoids a branch
}
return cnt;
}
Note the width is passed to the function.
On architectures with < 32 bits (PIC, AVR, MSP430, etc.) specialized versions will gain much better results than a single version.

Breaking apart bit patterns, shifting and creating new patterns

As part of a larger problem, I have to take some binary value: 00000000 11011110 (8)
Then, I have to:
Derive the bit count in this function - so I've done that by finding the place of the most sig fig.
Then store the first 6 numbers of this value into the value 128, such that it equals: 10011110
Then store the last 5 numbers of this value into the value 192, such that it equals: 11000011 10011110
The two bytes should be stored in some array, buffer[]
I have written this function however, position does not appear to initialise properly in gdb and the values are not outputting correctly. This is my attempt:
void create_value(unsigned short init_val, unsigned char buffer[])
{
// get the count
int position = 0;
while (init_val >>= 1)
position++;
// get total
int count = position++;
int start = 128;
for (int i = 0; i < 7; i++)
if (((1 << i) & init_val) != 0) start = start | 1 << i;
buffer[0] = start;
start = 192;
for (int i = 7; i < 11; i++) {
if (((1 << i) & init_val) !=0) start = start | 1 << i;
}
buf[1] = start;
}
After
while (init_val >>= 1)
position++;
init_val will be 0. When you later use
if (((1 << i) & init_val) != 0) start = start | 1 << i;
you will never change start.
So, after reading through what you're trying to do (which is pretty confusingly described), why don't you:
void create_value(unsigned short init_value, unsigned char buffer[])
{
buffer[0] = (init_value & 63) | 128;
buffer[1] = ((init_value >> 6) & 31) | 192;
return;
}
What this does: init_value & 63 masks off all but the lowest 6 bits in init_value, as you wanted. The | 128 then sets the most significant bit of the byte (IFF CHAR_BIT == 8, mind you).
(init_value >> 6) shifts init_value down by 6 bits, so now the original bits 6-11 are bits 0-4. & 31 masks off all bit the lowest 5 bits in this value, | 192 sets the two most significant bits.

8-bit Bitwise for 64 bit integer

I want to implement bitwise cyclic shift of a 64 bit integer.
ROT(a,b) will move bit at position i to position i+b. (a is the 64 bit integer)
However, my avr processor is an 8-bit processor. Thus, to express a, I have to use
unit8_t x[8].
x[0] is the 8 most significant bits of a.
x[7] is the 8 least significant bits of a.
Can any one help to implement ROT(a,b) in term of array x?
Thank you
It makes no functional difference if the underlying processor is 64-bit, 8-bit or 1-bit. If the compiler is compliant - you are good to go. Use uint64_t. Code does not "have to use unit8_t" because the processor is an 8-bit one.
uint64_t RPT(uint64_t a, unsigned b) {
return (a << (b & 63)) | (a >> ((64 - b) & 63));
}
Extra () added for explicitness.
& 63 (or %64 is you like that style) added to insure only 6 LSBits of b contribute to the shift. Any higher bits simply imply multiple "revolutions" of a circular shift.
((64 - b) & 63) could be simplified to (-b & 63).
--
But if OP still wants "implement ROT(a,b) in term of array unit8_t x[8]":
#include <stdint.h>
// circular left shift. MSByte in a[0].
void ROT(uint8_t *a, unsigned b) {
uint8_t dest[8];
b &= 63;
// byte shift
unsigned byte_shift = b / 8;
for (unsigned i = 0; i < 8; i++) {
dest[i] = a[(i + byte_shift) & 7];
}
b &= 7; // b %= 8; form bit shift;
unsigned acc = dest[0] << b;
for (unsigned i = 8; i-- > 0;) {
acc >>= 8;
acc |= (unsigned) dest[i] << b;
a[i] = (uint8_t) acc;
}
}
#vlad_tepesch Suggested a solution that emphasizes the AVR 8-bit nature. This is an untested attempt.
void ROT(uint8_t *a, uint8_t b) {
uint8_t dest[8];
b &= 63; // Could be eliminated as following code only uses the 6 LSBits.
// byte shift
uint8_t byte_shift = b / 8u;
for (uint8_t i = 0; i < 8u; i++) {
dest[i] = a[(i + byte_shift) & 7u];
}
b &= 7u; // b %= 8u; form bit shift;
uint16_t acc = dest[0] << b;
for (unsigned i = 8u; i-- > 0;) {
acc >>= 8u;
acc |= (uint8_t) dest[i] << b;
a[i] = (uint8_t) acc;
}
}
why do not leave the work to the compiler and just implement a function
uint64_t rotL(uint64_t v, uint8_t r){
return (v>>(64-r)) | (v<<r)
}
I take it the x(i) are 8 bits.
To rotate left n times
each bit from X(i,j) where i is the index array x(0) -> x(7)
and j is the bit position within the element
then this bit will end up in
Y((i+n)/8, ( i+n) & 7 )
This will handle rotations up to 63
any number > 63 , you just mod it.

Bytes to Binary in C

I'm trying to simply convert a byte received from fget into binary.
I know the value of the first byte was 49 based on printing the value. I now need to convert this into its binary value.
unsigned char byte = 49;// Read from file
unsigned char mask = 1; // Bit mask
unsigned char bits[8];
// Extract the bits
for (int i = 0; i < 8; i++) {
// Mask each bit in the byte and store it
bits[i] = byte & (mask << i);
}
// For debug purposes, lets print the received data
for (int i = 0; i < 8; i++) {
printf("Bit: %d\n",bits[i]);
}
This will print:
Bit: 1
Bit: 0
Bit: 0
Bit: 0
Bit: 16
Bit: 32
Bit: 0
Bit: 0
Press any key to continue . . .
Clearly, this is not a binary value. Any help?
The problem you're having is that your assignment isn't resulting in a true or false value.
bits[i] = byte & (mask << i);
This gets the value of the bit. You need to see if the bit is on or off, like this:
bits[i] = (byte & (mask << i)) != 0;
Change
bits[i] = byte & (mask << i);
to
bits[i] = (byte >> i) & mask;
or
bits[i] = (byte >> i) & 1;
or
bits[i] = byte & 1;
byte >>= 1;
One way, among many:
#include <stdio.h>
#include <limits.h>
int main(void) {
int i;
char bits[CHAR_BIT + 1];
unsigned char value = 47;
for (i = CHAR_BIT - 1; i >= 0; i -= 1) {
bits[i] = '0' + (value & 0x01);
value >>= 1;
}
bits[CHAR_BIT] = 0;
puts(bits);
return 0;
}
You may notice that your output has a couple 1's and 0's, but also powers of 2, such as 32. This is because after you isolate the bit you want using the mask, you still have to bit-shift it into the least-significant digit so that it shows up as a 1. Or you could use what other posts suggested, and instead of bit-shifting the result (something like 00001000 for example), you could simply use (result != 0) to fetch either a 1 or 0, since in C, false is 0, and comparisons such as != will return 1 as true (I think).
#include<Stdio.h>
#include <limits.h>
void main(void) {
unsigned char byte = 49;// Read from file
unsigned char mask = 1; // Bit mask
unsigned char bits[8];
int i, j = CHAR_BIT-1;
// Extract the bits
for ( i = 0; i < 8; i++,j--,mask = 1) {
// Mask each bit in the byte and store it
bits[i] =( byte & (mask<<=j)) != NULL;
}
// For debug purposes, lets print the received data
for (int i = 0; i < 8; i++) {
printf("%d", bits[i]);
}
puts("");
}
This addition in place of that will work:
bits[i]= byte & (mask << i);
bits[i] >>=i;

Resources