I would like to input 2 unsigned char variables:a and b. If use a(0) for bit 0 in a, I would like to swap a(6) to a(1) with b(6) to b(1). Finally I wish to get 2 new unsigned char_type variables:a1 and b1 with required bits swapped. I would love to know that is there method to address this issue in C language?
An further requirement is that add 2 variables: pa and pb to decide the start position for the length. For example: if pa=6, pb=7, I have to swap a(6) to a(1) with b(7) to b(2).
Any good solution?
I'd be inclined to use xor masking:
mask = 0x3e; // 0b00111110
diff = (a & mask) ^ (b & mask);
a1 = a ^ diff;
b1 = b ^ diff;
Aha. I get it now
unsigned const char mask = 0x3e;
usigned char a,b; // input somehow
unsigned char a2=a, b2=b;
a2 = (a2 & ~mask) | (b & mask);
b2 = (b2 & ~mask) | (a & mask);
Given integers, e.g.:
uint32_t a = 0xff00ff00;
uint32_t b = 0x00ff00ff;
This is how you swap entire values:
a ^= b;
b ^= a;
a ^= b;
If you want to swap only specific bits, add a mask there:
uint32_t mask = 0x0000ffff; // only swap the lower 16 bits
a ^= (b & mask);
b ^= (a & mask);
a ^= (b & mask);
The above requires 6 bitwise operations, whereas ecatmur's solution requires only 5.
Related
Write a function that swaps the highest bits in each nibble of the byte pointed to by the pointer b. (i.e. 0bAxxxBxxx -> 0bBxxxAxxx).
I have a predefined function with this prototype: void swapBits(uint8_t* b);
The solution that I came up with is not working -
void swapBits(uint8_t *b)
{
uint8_t bit1;
uint8_t bit2;
uint8_t x;
bit1 = (*b >> 4) & 1;
bit2 = (*b >> 8) & 1;
x = bit1 ^ bit2;
x = x << 4 | x << 8;
*b = *b ^ x;
}
there are couple problems:
to get 4th bit from the right you need to shift 3 times (not four)
xor is probably not what you need to use
here is fixed version:
void swapBits(uint8_t* b)
{
uint8_t bit1;
uint8_t bit2;
bit1 = ((*b >> 3) & 1) << 7; // get bit from one position and put it into another
bit2 = ((*b >> 7) & 1) << 3;
*b = (*b & 0x77) | bit1 | bit2; // clear already extracted bits and reset with new values
}
You are extracting the low bit in the high nibble and shift out the whole uint8_t for bit2. You need to extract the high bit in both.
Example:
void swapBits(uint8_t* b)
{
// shift down the high nibble and get its MSb
uint8_t bit1 = (*b >> 4) & 0b1000;
// get the MSb in the low nibble and shift it up
uint8_t bit2 = (*b & 0b1000) << 4;
// remove whatever values the MSbs had and replace them with the new values
*b = (*b & 0b01110111) | bit2 | bit1;
}
0b for binary literals is a gcc extension (but will become standard in C23). If you can't use it, use a plain 8 instead of 0b1000 and 0x77 instead of 0b01110111. I'm using the extension because it makes it easier to see the patterns.
A more generic version where you can supply the mask for the the bits to swap between the nibbles could look like this:
uint8_t swapBits(uint8_t b, uint8_t m) {
return (b & ~(m << 4 | m)) // remove the bits in the mask
| ((b >> 4) & m) // high nibble bits -> low nibble
| ((b & m) << 4); // low nibble bits -> high nibble
}
Demo
Your code does not work because you shift the byte values by 4 and 8 instead of 3 and 7.
Here is a modified version of your code:
void swapBits(uint8_t *b) {
uint8_t bit1 = (*b >> 3) & 1;
uint8_t bit2 = (*b >> 7) & 1;
uint8_t x = bit1 ^ bit2;
*b ^= (x << 3) | (x << 7);
}
Here is a simplified version:
void swapBits(uint8_t *b) {
uint8_t x = (*b ^ (*b >> 4)) & 0x08;
*b ^= x * 0x11;
}
Here is an alternative approach that can be used for more multiple bits:
void swapBits(uint8_t *b) {
uint8_t bit7 = (*b & 0x08) << 4;
uint8_t bit3 = (*b & 0x80) >> 4;
*b = (*b & 0x77) | bit7 | bit3;
}
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.
I'm working on this programming project and part of it is to write a function with just bitwise operators that switches every two bits. I've come up with a comb sort of algorithm that accomplishes this but it only works for unsigned numbers, any ideas how I can get it to work with signed numbers as well? I'm completely stumped on this one. Heres what I have so far:
// Mask 1 - For odd bits
int a1 = 0xAA; a1 <<= 24;
int a2 = 0xAA; a2 <<= 16;
int a3 = 0xAA; a3 <<= 8;
int a4 = 0xAA;
int mask1 = a1 | a2 | a3 | a4;
// Mask 2 - For even bits
int b1 = 0x55; b1 <<= 24;
int b2 = 0x55; b2 <<= 16;
int b3 = 0x55; b3 <<= 8;
int b4 = 0x55;
int mask2 = b1 | b2 | b3 | b4;
// Mask Results
int odd = x & mask1;
int even = x & mask2;
int newNum = (odd >> 1) | (even << 1);
return newNum;
The manual creation of the masks by or'ing variables together is because the only constants that can be used are between 0x00-0xFF.
The problem is that odd >> 1 will sign extend with negative numbers. Simply do another and to eliminate the duplicated bit.
int newNum = ((odd >> 1) & mask2) | (even << 1);
Minimizing the operators and noticing the sign extension problem gives:
int odd = 0x55;
odd |= odd << 8;
odd |= odd << 16;
int newnum = ((x & odd) << 1 ) // This is (sort of well defined)
| ((x >> 1) & odd); // this handles the sign extension without
// additional & -operations
One remark though: bit twiddling should be generally applied to unsigned integers only.
When you right shift a signed number, the sign will also be extended. This is known as sign extension. Typically when you are dealing with bit shifting, you want to use unsigned numbers.
Minimizing use of constants by working one byte at a time:
unsigned char* byte_p;
unsigned char byte;
int ii;
byte_p = &x;
for(ii=0; ii<4; ii++) {
byte = *byte_p;
*byte_p = ((byte & 0xAA)>>1) | ((byte & 0x55) << 1);
byte_p++;
}
Minimizing operations and keeping constants between 0x00 and 0xFF:
unsigned int comb = (0xAA << 8) + 0xAA;
comb += comb<<16;
newNum = ((x & comb) >> 1) | ((x & (comb >> 1)) << 1);
10 operations.
Just saw the comments above and realize this is implementing (more or less) some of the suggestions that #akisuihkonen made. So consider this a tip of the hat!
I had this interview question -
Swap byte 2 and byte 4 within an integer sequence.
Integer is a 4 byte wide i.e. 32 bits
My approach was to use char *pointer and a temp char to swap the bytes.
For clarity I have broken the steps otherwise an character array can be considered.
unsigned char *b2, *b4, tmpc;
int n = 0xABCD; ///expected output 0xADCB
b2 = &n; b2++;
b4 = &n; b4 +=3;
///swap the values;
tmpc = *b2;
*b2 = *b4;
*b4 = tmpc;
Any other methods?
int someInt = 0x12345678;
int byte2 = someInt & 0x00FF0000;
int byte4 = someInt & 0x000000FF;
int newInt = (someInt & 0xFF00FF00) | (byte2 >> 16) | (byte4 << 16);
To avoid any concerns about sign extension:
int someInt = 0x12345678;
int newInt = (someInt & 0xFF00FF00) | ((someInt >> 16) & 0x000000FF) | ((someInt << 16) & 0x00FF0000);
(Or, to really impress them, you could use the triple XOR technique.)
Just for fun (probably a tupo somewhere):
int newInt = someInt ^ ((someInt >> 16) & 0x000000FF);
newInt = newInt ^ ((newInt << 16) & 0x00FF0000);
newInt = newInt ^ ((newInt >> 16) & 0x000000FF);
(Actually, I just tested it and it works!)
You can mask out the bytes you want and shift them around. Something like this:
unsigned int swap(unsigned int n) {
unsigned int b2 = (0x0000FF00 & n);
unsigned int b4 = (0xFF000000 & n);
n ^= b2 | b4; // Clear the second and fourth bytes
n |= (b2 << 16) | (b4 >> 16); // Swap and write them.
return n;
}
This assumes that the "first" byte is the lowest order byte (even if in memory it may be stored big-endian).
Also it uses unsigned ints everywhere to avoid right shifting introducing extra 1s due to sign extension.
What about unions?
int main(void)
{
char tmp;
union {int n; char ary[4]; } un;
un.n = 0xABCDEF00;
tmp = un.ary[3];
un.ary[3] = un.ary[1];
un.ary[1] = tmp;
printf("0x%.2X\n", un.n);
}
in > 0xABCDEF00
out>0xEFCDAB00
Please don't forget to check endianess. this only work for little endian, but should not be hard to make it portable.
I am converting a number to binary and have to use putchar to output each number.
The problem is that I am getting the order in reverse.
Is there anyway to reverse a numbers bit pattern before doing my own stuff to it?
As in int n has a specific bit pattern - how can I reverse this bit pattern?
There are many ways to do this, some very fast. I had to look it up.
Reverse bits in a byte
b = ((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
Reverse an N-bit quantity in parallel in 5 * lg(N) operations:
unsigned int v; // 32-bit word to reverse bit order
// swap odd and even bits
v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1);
// swap consecutive pairs
v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2);
// swap nibbles ...
v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);
// swap bytes
v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8);
// swap 2-byte long pairs
v = ( v >> 16 ) | ( v << 16);
Reverse bits in word by lookup table
static const unsigned char BitReverseTable256[256] =
{
# define R2(n) n, n + 2*64, n + 1*64, n + 3*64
# define R4(n) R2(n), R2(n + 2*16), R2(n + 1*16), R2(n + 3*16)
# define R6(n) R4(n), R4(n + 2*4 ), R4(n + 1*4 ), R4(n + 3*4 )
R6(0), R6(2), R6(1), R6(3)
};
unsigned int v; // reverse 32-bit value, 8 bits at time
unsigned int c; // c will get v reversed
// Option 1:
c = (BitReverseTable256[v & 0xff] << 24) |
(BitReverseTable256[(v >> 8) & 0xff] << 16) |
(BitReverseTable256[(v >> 16) & 0xff] << 8) |
(BitReverseTable256[(v >> 24) & 0xff]);
// Option 2:
unsigned char * p = (unsigned char *) &v;
unsigned char * q = (unsigned char *) &c;
q[3] = BitReverseTable256[p[0]];
q[2] = BitReverseTable256[p[1]];
q[1] = BitReverseTable256[p[2]];
q[0] = BitReverseTable256[p[3]];
Please look at http://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel for more information and references.
Pop bits off your input and push them onto your output. Multiplying and dividing by 2 are the push and pop operations. In pseudo-code:
reverse_bits(x) {
total = 0
repeat n times {
total = total * 2
total += x % 2 // modulo operation
x = x / 2
}
return total
}
See modulo operation on Wikipedia if you haven't seen this operator.
Further points:
What would happen if you changed 2 to 4? Or to 10?
How does this effect the value of n? What is n?
How could you use bitwise operators (<<, >>, &) instead of divide and modulo? Would this make it faster?
Could we use a different algorithm to make it faster? Could lookup tables help?
Let me guess: you have a loop that prints the 0th bit (n&1), then shifts the number right. Instead, write a loop that prints the 31st bit (n&0x80000000) and shifts the number left. Before you do that loop, do another loop that shifts the number left until the 31st bit is 1; unless you do that, you'll get leading zeros.
Reversing is possible, too. Somthing like this:
unsigned int n = 12345; //Source
unsigned int m = 0; //Destination
int i;
for(i=0;i<32;i++)
{
m |= n&1;
m <<= 1;
n >>= 1;
}
I know: that is not exactly C, but I think that is an interesting answer:
int reverse(int i) {
int output;
__asm__(
"nextbit:"
"rcll $1, %%eax;"
"rcrl $1, %%ebx;"
"loop nextbit;"
: "=b" (output)
: "a" (i), "c" (sizeof(i)*8) );
return output;
}
The rcl opcode puts the shifted out bit in the carry flag, then rcr recovers that bit to another register in the reverse order.
My guess is that you have a integer and you're attempting to convert it to binary?
And the "answer" is ABCDEFG, but your "answer" is GFEDCBA?
If so, I'd double check the endian of the machine you're doing it on and the machine the "answer" came from.
Here are functions I've used to reverse bits in a byte and reverse bytes in a quad.
inline unsigned char reverse(unsigned char b) {
return (b&1 << 7)
| (b&2 << 5)
| (b&4 << 3)
| (b&8 << 1)
| (b&0x10 >> 1)
| (b&0x20 >> 3)
| (b&0x40 >> 5)
| (b&0x80 >> 7);
}
inline unsigned long wreverse(unsigned long w) {
return ( ( w &0xFF) << 24)
| ( ((w>>8) &0xFF) << 16)
| ( ((w>>16)&0xFF) << 8)
| ( ((w>>24)&0xFF) );
}