Dear list!
I have 2 pointers, let's call them source_ptr and destination_ptr. I want to copy 1 bit from the source byte to another bit of the destination byte. Are there a simple instruction to do that?
Example: source bit 2 to destination bit 5
Printable View
Dear list!
I have 2 pointers, let's call them source_ptr and destination_ptr. I want to copy 1 bit from the source byte to another bit of the destination byte. Are there a simple instruction to do that?
Example: source bit 2 to destination bit 5
That should work, but it involves a logical AND and bit shifting, which are likely to confuse you. I know of no *simple* ways to do it, and if you're trying to deal specifically with just bit 5 in dest and not affect the other bits, my code there won't work. You might want to check into bitfields, but chances are very good that whatever you're trying to accomplish can be done without manipulating bits like that. What are you trying to do, btw?Code:int source,dest,temp;
source=43;
dest=source&&2; //2 is 0000 0010 in binary
dest<<3; //shift it over to 3 bits so it's in the right spot
I agree and cannot see why you would need to do this.
Code:typedef unsigned long DWORD;
typedef unsigned int WORD;
DWORD ReplaceBit(DWORD source,DWORD target,WORD sourcebit,WORD destbit)
{
WORD bitmask=(WORD)pow(2,sourcebit);
WORD bitvalue=source&bitmask;
if (bitvalue) target+=(WORD)pow(2,destbit);
return target;
}
I've not tested this yet. I think it should work. It tests the sourcebit to see if it is 1 or not. If it is, it sets the destbit to 1 by adding pow(2,destbit) to the target value, if not then target does not need to be altered since the sourcebit evaluated to 0.
This function should work on any 8,16, or 32-bit non-floating point value. It does not check to make sure that the destbit and sourcebit are valid nor does it check for overflow condition in the target. Bit positions start at 0.
This function will not cause target to lose any data because it does not use shifting - unless target overflows.
Try it out. I'm not at my house right now so I cannot compile it and see if it works.
This works
It checks to see if the bit to be copied is set, if it is then the bit to be copied to is set, otherwise it's cleared. Not as easy as a direct assignment, but it does the trick. The operations look complicated, but they're totally idiomatic, just remember what they look like.Code:#define bit(n) (1UL << (n))
unsigned copybit(unsigned a, unsigned b, int abit, int bbit)
{
return (a & bit(abit)) ? b | bit(bbit) : b & ~bit(bbit);
}
a & bit(abit) tests a bit to see if it's set and returns zero if it isn't set and nonzero otherwise.
b | bit(bbit) sets the selected bit to 1
b & ~bit(bbit) clears the selected bit to 0
Well, I just need some code that copy 1 bit from source to destination and overwrites the destination bit whatever the value is and at the same time do not affect the other bits in source or destination. Maybe I can test the destination bit and set the source to the same state? Any code example for that?Quote:
Originally posted by blackrat364
That should work, but it involves a logical AND and bit shifting, which are likely to confuse you. I know of no *simple* ways to do it, and if you're trying to deal specifically with just bit 5 in dest and not affect the other bits, my code there won't work. You might want to check into bitfields, but chances are very good that whatever you're trying to accomplish can be done without manipulating bits like that. What are you trying to do, btw?Code:int source,dest,temp;
source=43;
dest=source&&2; //2 is 0000 0010 in binary
dest<<3; //shift it over to 3 bits so it's in the right spot
Good job Casey. Much nicer and cleaner than my code.
:)
Look at follwing Function:
unsigned char copybit(unsigned char a, unsigned char b, int abit, int bbit)
{
if(((1<<(bbit-1))&b) == 0)
return a & (~(1<<(abit-1)));
else
return a | (1<<(abit-1));
}
===
Copybit function replaces abit of a with bbit of b.
Consider bit number as follows:
Value : 1 1 1 1 1 1 1 1
Bit Num : 8 7 6 5 4 3 2 1
This isn't really the way to do it. Why? Because you have your AND operators mixed up. You need a bitwise and, not a logical. (Assuming that you didn't just typo that.)Quote:
Originally posted by blackrat364
Code:dest=source&&2; //2 is 0000 0010 in binary
dest<<3; //shift it over to 3 bits so it's in the right spot
The above expression evaluates to this:
dest = (source is not zero and 2 is not zero).
In which case, dest is now set to 1. If either of those two are not true, then dest is set to zero.
If you are just trying to copy a single bit, rather, if you are just trying to make dest equal to that one specific bit, you'd do:
So here you'd have:Code:dest = source & bit;
This would set dest to 2 if the bit for 2 is set. If it isn't, it sets it to zero.Code:dest = source & 2;
Quzah.
It wasn't exactly a typo, but I know better. It was just an early morning lack of sleep stupid thing. Thanks for catching that Quzah.
Not a problem. I know how that goes. You should have seen me yesterday... :DQuote:
Originally posted by blackrat364
It wasn't exactly a typo, but I know better. It was just an early morning lack of sleep stupid thing. Thanks for catching that Quzah.
Quzah.
One other small thing: dest<<3;
Ya just lost your shift there... How 'bout <<=. ;)
Absolutely fantastic solution!! I have tested the code now in my app and it does the job without asking for trouble :-))Quote:
Originally posted by Casey
This works
It checks to see if the bit to be copied is set, if it is then the bit to be copied to is set, otherwise it's cleared. Not as easy as a direct assignment, but it does the trick. The operations look complicated, but they're totally idiomatic, just remember what they look like.Code:#define bit(n) (1UL << (n))
unsigned copybit(unsigned a, unsigned b, int abit, int bbit)
{
return (a & bit(abit)) ? b | bit(bbit) : b & ~bit(bbit);
}
a & bit(abit) tests a bit to see if it's set and returns zero if it isn't set and nonzero otherwise.
b | bit(bbit) sets the selected bit to 1
b & ~bit(bbit) clears the selected bit to 0
Thanks for helping :-)
Wouldn't XORing be easier? Because basicly that's what you're doing.Quote:
Originally posted by Casey
It checks to see if the bit to be copied is set, if it is then the bit to be copied to is set, otherwise it's cleared.
Your code basicly just toggles the specified bit, so you may as well just do that.Code:unsigned int foo( unsigned int a, unsigned int b )
{
return (a^(1<<b));
}
Although, to be "safe", you'd probably want to "%(sizeof(b)<<3)" on B first to make sure it's actually in range...
Quzah.
no it doesn't. the code sets or resets a single bit in 'a' dependent on the value of a single bit in another int.Quote:
Your code basicly just toggles the specified bit, so you may as well just do that.
No, it actually doesn't even do that. Honestly, I am at a loss of how to use said function. Look at it again (I had to):Quote:
Originally posted by DavT
no it doesn't. the code sets or resets a single bit in 'a' dependent on the value of a single bit in another int.
No, it's damn messed up. Took me the longest time to actually figure out what it's doing. Here, let me illustrate:Code:#define bit(n) (1UL << (n))
unsigned copybit(unsigned a, unsigned b, int abit, int bbit)
{
return (a & bit(abit)) ? b | bit(bbit) : b & ~bit(bbit);
}
The code only sets the bit on b, if the bit in question on a is not set. If they are both set, nothing at all happens.Code:#include <stdio.h>
#define bit(n) (1UL << (n))
unsigned copybit(unsigned a, unsigned b, int abit, int bbit)
{
return (a & bit(abit)) ? b | bit(bbit) : b & ~bit(bbit);
}
void drawbit( unsigned int a )
{
int b = 0;
for( b = 0; b < 32; b++ )
printf("%d", !!(a & (1<<b)) );
printf("\n");
}
void dump( unsigned int a, unsigned int b )
{
int x,y;
for( x = y = 0; y < 16; y++ )
{
printf("x = %d, y is %2d: ", x, y );
drawbit( copybit( a, b, x, y ) );
}
printf("Hit enter.\n");
getchar( );
}
int main ( void )
{
unsigned int a = 0xFFFFFFFF, b = 0xFFFFFFFF;
dump( a, b );
a = 0x00000000;
dump( a, b );
b = 0x00000000;
dump( a, b );
a = 0xFFFFFFFF;
dump( a, b );
return 0;
}
As for practical application of a four argument bit toggle, I have no idea. This isn't meant as an insult to the author, I just am boggled by it. Maybe I'm tired. That's always a good excuse...
On a side note, you are correct in saying I was wrong.
[edit]
Test output is way too huge to list.
Picture 16 lines of 1s, followed by 16 lines where there is a zero that moves down the row of ones:
011...
101...
110...
Followed by 16 lines of 0s, followed by 16 lines of a traveling one.
[/edit]
[edit #2]
Ok, nevermind. You and I were both wrong. (I finally wrapped my mind around it as I was about to drop into bead.) It performas as it should. (At least that's what I'm convincing myself of now.)
The example output from the text function should confirm it.
If both bits are the same, then it is indeed copying the value to that location, (in b), which is why we get a solid output of 1s. If they are different, it does in fact copy that result to said bit, which is why we get the "traveling 1" or "traveling 0" effect.
We were both incorrect. The reason for the confusion was the way they worded what it does:
It should read:Quote:
It checks to see if the bit to be copied is set, if it is then the bit to be copied to is set, otherwise it's cleared.
"If the source bit and the destination bit are both set, nothing changes. If one is set and the other isn't, the bit is 'toggled'."
[/edit #2]
Quzah.
This is the same technique as already presented, but it is targeted toward the original intent: two (presumably unsigned char) pointers and two bit locations.Quote:
Originally posted by Coder2Die4
I have 2 pointers, let's call them source_ptr and destination_ptr. I want to copy 1 bit from the source byte to another bit of the destination byte. Are there a simple instruction to do that?
Example: source bit 2 to destination bit 5
Note also that my bits (srcbit, dstbit) are 'numbered' 0-7 rather than the example that had them as 1-8.Code:#include <stdio.h>
#include <limits.h>
void bitcpy(unsigned char *dst, unsigned char dstbit,
const unsigned char *src, unsigned char srcbit)
{
if ( *src & (1 << srcbit) ) /* if srcbit is '1' in source byte */
{
*dst |= (1 << dstbit); /* set dstbit in destination byte */
}
else /* else srcbit is '0' in source byte */
{
*dst &= ~(1 << dstbit); /* clear dstbit in destination byte */
}
}
void showbits(unsigned char byte)
{
unsigned char bit;
printf("0x%02X = ", byte);
for ( bit = 1 << ((sizeof(byte) * CHAR_BIT) - 1); bit; bit >>= 1 )
{
putchar(byte & bit ? '1' : '0');
}
putchar('\n');
}
int main(void)
{
int i;
unsigned char result = 0xFF, value = 0x3A;
fputs("result: ", stdout); showbits(result);
fputs("value: ", stdout); showbits(value);
bitcpy(&result, 5, &value, 2);
puts("*** bitcpy ***");
fputs("result: ", stdout); showbits(result);
puts("*** reverse bits ***");
fputs("value: ", stdout); showbits(value);
for ( i = 0; i < CHAR_BIT; ++i )
{
bitcpy(&result, (CHAR_BIT - 1) - i, &value, i);
}
fputs("result: ", stdout); showbits(result);
return 0;
}
/* my output
result: 0xFF = 11111111
value: 0x3A = 00111010
*** bitcpy ***
result: 0xDF = 11011111
*** reverse bits ***
value: 0x3A = 00111010
result: 0x5C = 01011100
*/