Is there a way to manipulate the bits that I shift in C - c

If I have an int a, which is lets say equal to 0.
Is there a way for me to say left shift 101 into the variable and then in another step shift in 011 into it? Then I could get the int decimal number at the end? It would end up becoming 0b00000000000000000000000000101011.Or should I only use the OR operation.

You can't shift bits into the variable; you can OR them in:
int a = 0;
a |= 5;
printf("a = %d\n", a);
a <<= 3;
a |= 3;
printf("a = %d\n", a);
If your system supports binary constants, you can use those instead of decimals (and you can prefix 5 and 3 with 0 for octal or 0x for hexadecimal if you prefer — and you can print with a different format according to taste, too). If the starting value for a isn't known to be 0, you would do a shift-assignment operation before the first |= operation.
Eventually, you have to worry about left-shifting a signed integer value such that overflow occurs — that leads to undefined behaviour. It isn't a problem with the values in the question, though.

You would need to first shift by the required number of bits then perform a bitwise OR of the new data.
int a = 0;
a = a << 3;
a = a | 0x5;
a = a << 3;
a = a | 0x3;
printf("a=%x\n", a);
( Used separate assignments and operators instead of compound operators to make it clearer to beginners. )
Result:
a=2b

Is there a way for me to say left shift 101 into the variable
No. You need to left shift first, then add (or OR) the new value.
int eax = 0;
eax <<= 3;
eax |= 5;

int a = 0;
a << 3;
a |= 0x5;
a << 3;
a |= 0x3;
There isn't a predefined way to "shift in" a value like that. It wouldn't take much time to write a function that could though.

There is - to my knowledge - no operation that "shifts" a number of bits from one integer into another. The left shift operator always fills the arising spaces with 0, such that you have to combine it with, for example, an |-operation (actually a + would have the same effect in your case).
#include <stdio.h>
void printBinary(int b, int nrOfBits) {
for (int mask = (1 << nrOfBits); mask != 0; mask >>=1 ) {
char c = (b & mask) ? '1' : '0';
printf("%c", c);
}
}
int main()
{
int a = 0;
a = (a << 3) | 0x5;
printBinary(a, 8);printf("\n");
a = (a << 3) | 0x3;
printBinary(a, 8);printf("\n");
return 0;
}
When using left shift operators on signed datatypes be careful not to produce undefined behaviour (cf. cppreference concerting arithmetic operations):
When signed integer arithmetic operation overflows (the result does
not fit in the result type), the behavior is undefined

Related

Combining four 16bit numbers into single 64bit number

I need to combine four numbers in hex format into single number. The first option that I thought of was to do left shift by n*16 (n=0,1,2,3..) for each number.
This works fine when the numbers are 0xABCD.
If a number is 0x000A, the leading zeroes are ignored and whole thing stops working (not performs as expected).
I need to have all the leading zeroes because I have to know the position of 1's in the 64bit number.
user.profiles is a 64bit value where the each part of tmp_arr is shifted to the left and stored. Am I missing something here? Or am I just going crazy?
for(int i = 0; i < 4; i++)
{
EE_ReadVariable(EE_PROFILES_1 + i, &tmp_arr[i]); // increment the address by i (D1->D2->D3->D4)
user.profiles |= (tmp_arr[i] << (i*16)); // shift the value by multiples of 16 to get 64bit number
}
C allows type-punning using unions, so you could have something like this:
union value_union
{
uint16_t v16[4];
uint64_t v64;
};
// ...
union value_union values;
values.v16[0] = value1;
values.v16[1] = value2;
values.v16[2] = value3;
values.v16[3] = value4;
printf("64-bit value = 0x%016"PRIx64"\n", values.v64);
In order to write embedded C, it is very important that you know of Implicit type promotion rules.
tmp_arr[i] << (i*16) on a 32 bit system like STM32 promotes the tmp_arr[i] argument to 32 bit signed int. This comes with two complications:
If you happen to shift a value into the sign bit of this 32 bit int, you get an undefined behavior bug.
If you shift beyond the size of this 32 bit int, you get an undefined behavior bug (and data shifted out is lost.
You need to use 64 bit unsigned arithmetic for this (which will be fairly inefficient on a 32 bitter):
user.profiles |= (uint64_t)tmp_arr[i] << i*16;
The size and type of what's on the left side of the assignment operator is completely irrelevant here.
Also, when coding for embedded systems get rid of sloppy int and the other "primitive" default types, use the types of stdint.h only. In the average embedded system, you rarely ever want any signed types, they just create problems. For STM32, you'll want to use uint32_t in most cases.
As I mentioned in the comments, you need to cast your uint16_t temporary to uint64_t before shifting up and you should check for errors.
The "missing" leading zeroes probably comes from using the wrong format for printf.
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
uint64_t get_profiles() {
uint64_t rv = 0;
uint16_t tmp;
for(int i = 0; i < 4; i++) {
uint16_t res = EE_ReadVariable(EE_PROFILES_1 + i, &tmp);
switch(res) {
case 0: rv |= (uint64_t)tmp << i*16; break;
case 1: /* variable not found */ break; // deal with error
case NO_VALID_PAGE: /* no valid page found */ break; // deal with error
}
}
return rv;
}
int main () {
// ...
user.profiles = get_profiles();
printf("%016" PRIx64 "\n", user.profiles); // prints leading zeroes
}
You can avoid casting and the need to force intermediate 64-bit arithmetic by shifting the target and masking into the least significant 16 bits in two separate implicitly 64 bit operations, thus:
user.profiles = 0u ;
for(int i = 0; i < 4; i++)
{
EE_ReadVariable( EE_PROFILES_1 + i, &tmp_arr[i] ) ;
user.profiles <<= 16 ;
user.profiles |= tmp_arr[i] ;
}
In the shift-assignment and the OR-assignment, the right-hand operand it is implicitly promoted the same type as the right hand.
If tmp_arr is not used then:
user.profiles = 0u ;
for(int i = 0; i < 4; i++)
{
uint16_t tmp = 0 ;
EE_ReadVariable( EE_PROFILES_1 + i, &tmp ) ;
user.profiles <<= 16 ;
user.profiles |= tmp ;
}

Unusual behavior with shift-right bitwise operator

I'm writing a simple code in C (only using bit-wise operators) that takes a pointer to an unsigned integer x and flips the bit at the nth position n in the binary notation of the integer. The function is declared as follows:
int flip_bit (unsigned * x, unsigned n);
It is assumed that n is between 0 and 31.
In one of the steps, I perform a shift-right operation, but the results are not what I expect. For instance, if I do 0x8000000 >> 30, I get 0xfffffffe as a result, which are 1000 0000 ... 0000 and 1111 1111 ... 1110, respectively, in binary notation. (The expected result is0000 0000 ... 0010).
I am unsure of how or where I am making the mistake. Any help would be appreciated. Thanks.
Edit 1: Below is the code.
#include <stdio.h>
#define INTSIZE 31
void flip_bit(unsigned * x,
unsigned n) {
int a, b, c, d, e, f, g, h, i, j, k, l, m, p, q;
// save bits on the left of n and insert a zero at the end
a = * x >> n + 1;
b = a << 1;
// save bits on the right of n
c = * x << INTSIZE - (n - 1);
d = c >> INTSIZE - (n - 1);
// shift the bits to the left (back in their positions)
// combine all bits
e = d << n;
f = b | e;
// Isolating the nth bit in its position
g = * x >> n;
h = g << INTSIZE;
// THIS LINE BELOW IS THE ONE CAUSING TROUBLE.
i = h >> INTSIZE - n;
// flipping all bits and removing the 1s surrounding
// the nth bit (0 or 1)
j = ~i;
k = j >> n;
l = k << INTSIZE;
p = l >> INTSIZE - n;
// combining the value missing nth bit and
// the one with the flipped one
q = f | p;
* x = q;
}
I'm getting the unusual behavior when I run flip_bit(0x0000004e,0). The line for the shift-right operation in question has comments in uppercase above it.
There is probably a shorter way to do this (without using a thousand variables), but that's what I have now.
Edit 2: The problem was that I declared the variables as int (instead of unsigned). Nevertheless, that's a terrible way to solve the question. #old_timer suggested returning *x ^ (1u << n), which is much better.
The issue here is that you're performing a right shift on a signed int.
From section 6.5.7 of the C standard:
5 The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative
value, the value of the result is the integral part of the quotient of
E1 / 2E2. If E1 has a signed type and a negative value, the
resulting value is implementation-defined.
The bold part is what's happening in your case. Each of your intermediate variables are of type int. Assuming your system uses 2's complement representations for negative numbers, any int value with the high bit set is interpreted as a negative value.
The most common implementation-defined behavior behavior you'll see (and this in fact what gcc and MSVC both do) in this case is that if the high bit is set on a signed value then a 1 will be shifted in on a right shift. This preserves the sign of the value and makes x >> n equivalent to x / 2n for all signed and unsigned values.
You can fix this by changing all of your intermediate variables to unsigned. That way, they match the type of *x and you won't get 1s pushed on to the left.
As for your method of flipping a bit, there is a much simpler way of doing so. You can instead use the ^ operator, which is the bitwise exclusive OR operator.
From section 6.5.11 of the C standard:
4 The result of the ^ operator is the bitwise exclusive OR (XOR) of the
operands (that is, each bit in the result is set if and only if
exactly one of the corresponding bits in the converted operands is
set).
For example:
0010 1000
^ 1100 ^ 1101
------ ------
1110 0101
Note that you can use this to create a bitmask, then use that bitmask to flip the bits in the other operand.
So if you want to flip bit n, take the value 1, left shift it by n to move that bit to the desired location then XOR that value with your target value to flip that bit:
void flip_bit(unsigned * x, unsigned n) {
return *x = *x ^ (1u << n);
}
You can also use the ^= operator in this case which XORs the right operand to the left and assigns the result to the left:
return *x ^= (1u << n);
Also note the u suffix on the integer constant. That causes the type of the constant to be unsigned which helps to avoid the implementation defined behavior you experienced.
#include <stdio.h>
int main ( void )
{
unsigned int x;
int y;
x=0x80000000;
x>>=30;
printf("0x%08X\n",x);
y=0x80000000;
y>>=30;
printf("0x%08X\n",y);
return(0);
}
gcc on mint
0x00000002
0xFFFFFFFE
or what about this
#include <stdio.h>
int main ( void )
{
unsigned int x;
x=0x12345678;
x^=1<<30;
printf("0x%08X\n",x);
}
output
0x52345678

why the left shift operation does not work

I have the following code, where we try to left shift certain bits of a value:
int main()
{
unsigned long mvb = 1;
mvb << 8;
printf("The shift value is %u\n", mvb);
mvb << 56;
printf("The shift value is %u\n", mvb);
}
but the result for all those two operation are both 1, what is the reason, and how use it correctly?
You need to assign it back to mvb after shifting like:
mvb = mvb << 8;
%u is the wrong format specifier for an unsigned long, so the program behaviour is undefined. Use %lu instead.
Note that you're not actually changing the value of mvb: the printf calls are operating on the original value of mvb.
Writing mvb <<= 8 is the fix (this is using the bitwise left shift assigment operator), but be careful not to apply a shift beyond the number of bits in your type, as that is also undefined behaviour in C. For the avoidance of doubt, the undefined behaviour only results if you shift by too many bits at once: the subsequent shift of mvb <<= 56 is fine for a 64 bit type, but mvb <<= (8 + 56) would not be.

Left Bit Shift In C without extension

I was wondering how to get C to not extend my binary number when I bitshift to the left
int main ()
{
unsigned int binary_temp = 0b0100;
binary_temp = binary_temp << 2;
printf("%d", binary_temp);
return 0;
}
When I run that I want a return value of 0 since it has extended past the 4 digits I have, but right now it returns 16 (10000). How would I get C not to extend my number?
Edit: I would like to be able to work with the number in binary form so I need to have only 4 digits, and not just outputting the right number.
It does not extend your number but saves it as unsigned int type which is 4 bytes (32 bits) in size. You only fill the last 4 bits. To treat it as only 4 bits, use Bitwise AND with a Mask value. Here's example code:
int main()
{
unsigned int binary_temp = 0b0100;
binary_temp = (binary_temp << 2) & 0b1111;
printf("%u", binary_temp);
return 0;
}
You can bitwise AND the result with a 4 bit mask value:
binary_temp = (binary_temp << 2) & 0xF;
There is no 0b in standard C. You could use 4.
unsigned int /* prepare for wtf identifier: */
binary_temp = 4;
Left shifting by 2 is multiplying by 4. Why not?
binary_temp *= 4;
... and then reduce modulo 16?
binary_temp %= 16;
What sense is there to using binary operators, in this case? I see none.
The %d directive corresponds to an int argument, but the argument you're giving printf is an unsigned int. That's undefined behaviour.
printf("%u", binary_temp);
I'm sure whichever book you're reading will tell you about the %u directive.

Bit reversal of an integer, ignoring integer size and endianness

Given an integer typedef:
typedef unsigned int TYPE;
or
typedef unsigned long TYPE;
I have the following code to reverse the bits of an integer:
TYPE max_bit= (TYPE)-1;
void reverse_int_setup()
{
TYPE bits= (TYPE)max_bit;
while (bits <<= 1)
max_bit= bits;
}
TYPE reverse_int(TYPE arg)
{
TYPE bit_setter= 1, bit_tester= max_bit, result= 0;
for (result= 0; bit_tester; bit_tester>>= 1, bit_setter<<= 1)
if (arg & bit_tester)
result|= bit_setter;
return result;
}
One just needs first to run reverse_int_setup(), which stores an integer with the highest bit turned on, then any call to reverse_int(arg) returns arg with its bits reversed (to be used as a key to a binary tree, taken from an increasing counter, but that's more or less irrelevant).
Is there a platform-agnostic way to have in compile-time the correct value for max_int after the call to reverse_int_setup(); Otherwise, is there an algorithm you consider better/leaner than the one I have for reverse_int()?
Thanks.
#include<stdio.h>
#include<limits.h>
#define TYPE_BITS sizeof(TYPE)*CHAR_BIT
typedef unsigned long TYPE;
TYPE reverser(TYPE n)
{
TYPE nrev = 0, i, bit1, bit2;
int count;
for(i = 0; i < TYPE_BITS; i += 2)
{
/*In each iteration, we swap one bit on the 'right half'
of the number with another on the left half*/
count = TYPE_BITS - i - 1; /*this is used to find how many positions
to the left (and right) we gotta move
the bits in this iteration*/
bit1 = n & (1<<(i/2)); /*Extract 'right half' bit*/
bit1 <<= count; /*Shift it to where it belongs*/
bit2 = n & 1<<((i/2) + count); /*Find the 'left half' bit*/
bit2 >>= count; /*Place that bit in bit1's original position*/
nrev |= bit1; /*Now add the bits to the reversal result*/
nrev |= bit2;
}
return nrev;
}
int main()
{
TYPE n = 6;
printf("%lu", reverser(n));
return 0;
}
This time I've used the 'number of bits' idea from TK, but made it somewhat more portable by not assuming a byte contains 8 bits and instead using the CHAR_BIT macro. The code is more efficient now (with the inner for loop removed). I hope the code is also slightly less cryptic this time. :)
The need for using count is that the number of positions by which we have to shift a bit varies in each iteration - we have to move the rightmost bit by 31 positions (assuming 32 bit number), the second rightmost bit by 29 positions and so on. Hence count must decrease with each iteration as i increases.
Hope that bit of info proves helpful in understanding the code...
The following program serves to demonstrate a leaner algorithm for reversing bits, which can be easily extended to handle 64bit numbers.
#include <stdio.h>
#include <stdint.h>
int main(int argc, char**argv)
{
int32_t x;
if ( argc != 2 )
{
printf("Usage: %s hexadecimal\n", argv[0]);
return 1;
}
sscanf(argv[1],"%x", &x);
/* swap every neigbouring bit */
x = (x&0xAAAAAAAA)>>1 | (x&0x55555555)<<1;
/* swap every 2 neighbouring bits */
x = (x&0xCCCCCCCC)>>2 | (x&0x33333333)<<2;
/* swap every 4 neighbouring bits */
x = (x&0xF0F0F0F0)>>4 | (x&0x0F0F0F0F)<<4;
/* swap every 8 neighbouring bits */
x = (x&0xFF00FF00)>>8 | (x&0x00FF00FF)<<8;
/* and so forth, for say, 32 bit int */
x = (x&0xFFFF0000)>>16 | (x&0x0000FFFF)<<16;
printf("0x%x\n",x);
return 0;
}
This code should not contain errors, and was tested using 0x12345678 to produce 0x1e6a2c48 which is the correct answer.
typedef unsigned long TYPE;
TYPE reverser(TYPE n)
{
TYPE k = 1, nrev = 0, i, nrevbit1, nrevbit2;
int count;
for(i = 0; !i || (1 << i && (1 << i) != 1); i+=2)
{
/*In each iteration, we swap one bit
on the 'right half' of the number with another
on the left half*/
k = 1<<i; /*this is used to find how many positions
to the left (or right, for the other bit)
we gotta move the bits in this iteration*/
count = 0;
while(k << 1 && k << 1 != 1)
{
k <<= 1;
count++;
}
nrevbit1 = n & (1<<(i/2));
nrevbit1 <<= count;
nrevbit2 = n & 1<<((i/2) + count);
nrevbit2 >>= count;
nrev |= nrevbit1;
nrev |= nrevbit2;
}
return nrev;
}
This works fine in gcc under Windows, but I'm not sure if it's completely platform independent. A few places of concern are:
the condition in the for loop - it assumes that when you left shift 1 beyond the leftmost bit, you get either a 0 with the 1 'falling out' (what I'd expect and what good old Turbo C gives iirc), or the 1 circles around and you get a 1 (what seems to be gcc's behaviour).
the condition in the inner while loop: see above. But there's a strange thing happening here: in this case, gcc seems to let the 1 fall out and not circle around!
The code might prove cryptic: if you're interested and need an explanation please don't hesitate to ask - I'll put it up someplace.
#ΤΖΩΤΖΙΟΥ
In reply to ΤΖΩΤΖΙΟΥ 's comments, I present modified version of above which depends on a upper limit for bit width.
#include <stdio.h>
#include <stdint.h>
typedef int32_t TYPE;
TYPE reverse(TYPE x, int bits)
{
TYPE m=~0;
switch(bits)
{
case 64:
x = (x&0xFFFFFFFF00000000&m)>>16 | (x&0x00000000FFFFFFFF&m)<<16;
case 32:
x = (x&0xFFFF0000FFFF0000&m)>>16 | (x&0x0000FFFF0000FFFF&m)<<16;
case 16:
x = (x&0xFF00FF00FF00FF00&m)>>8 | (x&0x00FF00FF00FF00FF&m)<<8;
case 8:
x = (x&0xF0F0F0F0F0F0F0F0&m)>>4 | (x&0x0F0F0F0F0F0F0F0F&m)<<4;
x = (x&0xCCCCCCCCCCCCCCCC&m)>>2 | (x&0x3333333333333333&m)<<2;
x = (x&0xAAAAAAAAAAAAAAAA&m)>>1 | (x&0x5555555555555555&m)<<1;
}
return x;
}
int main(int argc, char**argv)
{
TYPE x;
TYPE b = (TYPE)-1;
int bits;
if ( argc != 2 )
{
printf("Usage: %s hexadecimal\n", argv[0]);
return 1;
}
for(bits=1;b;b<<=1,bits++);
--bits;
printf("TYPE has %d bits\n", bits);
sscanf(argv[1],"%x", &x);
printf("0x%x\n",reverse(x, bits));
return 0;
}
Notes:
gcc will warn on the 64bit constants
the printfs will generate warnings too
If you need more than 64bit, the code should be simple enough to extend
I apologise in advance for the coding crimes I committed above - mercy good sir!
There's a nice collection of "Bit Twiddling Hacks", including a variety of simple and not-so simple bit reversing algorithms coded in C at http://graphics.stanford.edu/~seander/bithacks.html.
I personally like the "Obvious" algorigthm (http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious) because, well, it's obvious. Some of the others may require less instructions to execute. If I really need to optimize the heck out of something I may choose the not-so-obvious but faster versions. Otherwise, for readability, maintainability, and portability I would choose the Obvious one.
Here is a more generally useful variation. Its advantage is its ability to work in situations where the bit length of the value to be reversed -- the codeword -- is unknown but is guaranteed not to exceed a value we'll call maxLength. A good example of this case is Huffman code decompression.
The code below works on codewords from 1 to 24 bits in length. It has been optimized for fast execution on a Pentium D. Note that it accesses the lookup table as many as 3 times per use. I experimented with many variations that reduced that number to 2 at the expense of a larger table (4096 and 65,536 entries). This version, with the 256-byte table, was the clear winner, partly because it is so advantageous for table data to be in the caches, and perhaps also because the processor has an 8-bit table lookup/translation instruction.
const unsigned char table[] = {
0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF};
const unsigned short masks[17] =
{0,0,0,0,0,0,0,0,0,0X0100,0X0300,0X0700,0X0F00,0X1F00,0X3F00,0X7F00,0XFF00};
unsigned long codeword; // value to be reversed, occupying the low 1-24 bits
unsigned char maxLength; // bit length of longest possible codeword (<= 24)
unsigned char sc; // shift count in bits and index into masks array
if (maxLength <= 8)
{
codeword = table[codeword << (8 - maxLength)];
}
else
{
sc = maxLength - 8;
if (maxLength <= 16)
{
codeword = (table[codeword & 0X00FF] << sc)
| table[codeword >> sc];
}
else if (maxLength & 1) // if maxLength is 17, 19, 21, or 23
{
codeword = (table[codeword & 0X00FF] << sc)
| table[codeword >> sc] |
(table[(codeword & masks[sc]) >> (sc - 8)] << 8);
}
else // if maxlength is 18, 20, 22, or 24
{
codeword = (table[codeword & 0X00FF] << sc)
| table[codeword >> sc]
| (table[(codeword & masks[sc]) >> (sc >> 1)] << (sc >> 1));
}
}
How about:
long temp = 0;
int counter = 0;
int number_of_bits = sizeof(value) * 8; // get the number of bits that represent value (assuming that it is aligned to a byte boundary)
while(value > 0) // loop until value is empty
{
temp <<= 1; // shift whatever was in temp left to create room for the next bit
temp |= (value & 0x01); // get the lsb from value and set as lsb in temp
value >>= 1; // shift value right by one to look at next lsb
counter++;
}
value = temp;
if (counter < number_of_bits)
{
value <<= counter-number_of_bits;
}
(I'm assuming that you know how many bits value holds and it is stored in number_of_bits)
Obviously temp needs to be the longest imaginable data type and when you copy temp back into value, all the extraneous bits in temp should magically vanish (I think!).
Or, the 'c' way would be to say :
while(value)
your choice
We can store the results of reversing all possible 1 byte sequences in an array (256 distinct entries), then use a combination of lookups into this table and some oring logic to get the reverse of integer.
Here is a variation and correction to TK's solution which might be clearer than the solutions by sundar. It takes single bits from t and pushes them into return_val:
typedef unsigned long TYPE;
#define TYPE_BITS sizeof(TYPE)*8
TYPE reverser(TYPE t)
{
unsigned int i;
TYPE return_val = 0
for(i = 0; i < TYPE_BITS; i++)
{/*foreach bit in TYPE*/
/* shift the value of return_val to the left and add the rightmost bit from t */
return_val = (return_val << 1) + (t & 1);
/* shift off the rightmost bit of t */
t = t >> 1;
}
return(return_val);
}
The generic approach hat would work for objects of any type of any size would be to reverse the of bytes of the object, and the reverse the order of bits in each byte. In this case the bit-level algorithm is tied to a concrete number of bits (a byte), while the "variable" logic (with regard to size) is lifted to the level of whole bytes.
Here's my generalization of freespace's solution (in case we one day get 128-bit machines). It results in jump-free code when compiled with gcc -O3, and is obviously insensitive to the definition of foo_t on sane machines. Unfortunately it does depend on shift being a power of 2!
#include <limits.h>
#include <stdio.h>
typedef unsigned long foo_t;
foo_t reverse(foo_t x)
{
int shift = sizeof (x) * CHAR_BIT / 2;
foo_t mask = (1 << shift) - 1;
int i;
for (i = 0; shift; i++) {
x = ((x & mask) << shift) | ((x & ~mask) >> shift);
shift >>= 1;
mask ^= (mask << shift);
}
return x;
}
int main() {
printf("reverse = 0x%08lx\n", reverse(0x12345678L));
}
In case bit-reversal is time critical, and mainly in conjunction with FFT, the best is to store the whole bit reversed array. In any case, this array will be smaller in size than the roots of unity that have to be precomputed in FFT Cooley-Tukey algorithm. An easy way to compute the array is:
int BitReverse[Size]; // Size is power of 2
void Init()
{
BitReverse[0] = 0;
for(int i = 0; i < Size/2; i++)
{
BitReverse[2*i] = BitReverse[i]/2;
BitReverse[2*i+1] = (BitReverse[i] + Size)/2;
}
} // end it's all

Resources