I did try the c++ <bitset> class to replace the PB's BIT function/statement,
but C++ doesn't serve the same purpose, because you can't set/reset a specific bit within any array type.
Do you know a C/C++ code that does exactly the same than PB ?
...
I think it can be done using ASM.
However then its not more easily convertible to x64.
I know in essence how to do it, but my limited knowledge of the C/C++ syntax for bit manipulation is what i must master first.
Here is one that should work with bits stored in a long array. (sorry for the cryptic C/C++ syntax) :-X
void BitSet(IN long data[], IN long b) {
data[b / 32] |= (1 << (b % 32));
}
void BitReSet(IN long data[], IN long b) {
data[b / 32] &= ~(1 << (b % 32));
}
bool BitGet(IN long data[], IN long b) {
return ( data[b / 32] & (1 << (b % 32)) );
}
Hi Patrice,
Interesting question - I hardly ever use bits but here is my best effort: This will support arrays. I use a pointer for the number parameter in all the calls.
/* bit testing and setting example */
#include <stdio.h>
int Bit(int *n,int i)
{
if ((*n & 1<<i)==0) return 0; else return 1;
}
void BitSet(int *n,int i)
{
*n |= 1<<i;
}
void BitReset(int *n,int i)
{
int b=~(1<<i);
*n &=b;
}
void BitToggle(int *n,int i)
{
int b=1<<i;
*n ^=b;
}
int main ()
{
//tests
int m[]={0x5,0xd,0x15};
int i=1;
printf ("%i\n", Bit(&m[i],1));
BitSet(&m[i],1);
printf ("%i\n", Bit(&m[i],1));
BitReset(&m[i],1);
printf ("%i\n", Bit(&m[i],1));
BitToggle(&m[i],1);
printf ("%i\n", Bit(&m[i],1));
BitToggle(&m[i],1);
printf ("%i\n", Bit(&m[i],1));
printf ("%x\n", m[i]);
return 0;
}
Charles
Perhaps less cryptic with the use of a macro.
#define BitMask(b) (1 << (b % 32))
void BitSet(IN long data[], IN long b) {
data[b / 32] |= BitMask(b);
}
void BitReSet(IN long data[], IN long b) {
data[b / 32] &= ~BitMask(b);
}
bool BitGet(IN long data[], IN long b) {
return ( data[b / 32] & BitMask(b) );
}
Beware modulo and division are deadly slow! :)
Charles
How would you set / reset a bit in a char array with yours?
(i mean how to call the Bitset)
...
You can use an int cast to override different types
char c[] ...
BitReset((int*)&c[ i ],1);
Patrice,
I think my use of casts with chars could cause problems, due to the mask potentially operating over the char boundary.
Your idea of using macros is safer and cleaner, (though the macros turn out incomprehensible :) )
/* bit testing and setting using macros */
#include <stdio.h>
#define Bit(a,n,i) if ((n & 1<<i)==0) a=0; else a=1
#define BitSet(n,i) n |=(1<<i)
#define BitReset(n,i) n &=(~(1<<i))
#define BitToggle(n,i) n ^=(1<<i)
int main ()
{
//tests
int m[]={0x5,0xd,0x15};
char c[100]="@EF";
int b=1;
int a;
Bit(a,m[1],b);
printf ("%x\n", a);
Bit(a,c[1],b);
printf ("%x\n", a);
BitToggle(c[1],b);
printf ("%x\n", c[1]);
BitToggle(c[1],b);
printf ("%x\n", c[1]);
return 0;
}
Charles
Yep, macro could be the way to go, because the code must work in both 32/64-bit.
The previous example you posted would work only in 32-bit, because we need to use LONG_PTR instead of int.
Testing your macro version right now on 64-bit.
...
Charles
The macro version doesn't work, at least with VS2010, using long array and LONG_PTR.
They should work with any type as they do in gcc, including arrays.
Do we need extra brackets to enforce precedence?
Charles
Here is exaclty what i want to do:
#include "stdafx.h"
#include <windows.h> // Search along the path.
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
#define MyBitTest(Var, Pos) ((Var) & (1 << (Pos)))
#define BitMask(BitPos) (1 << (BitPos % 32))
#define UsingLongArray(ArrayName) (LONG_PTR*) &ArrayName[0]
void BitSet(IN LONG_PTR *data, IN long BitPos) {
data[BitPos >> 5] |= BitMask(BitPos);
}
bool BitGet(IN LONG_PTR *data, IN long BitPos) {
return ( data[BitPos >> 5] & BitMask(BitPos) );
}
void BitReset(IN LONG_PTR *data, IN long BitPos) {
data[BitPos >> 5] &= ~BitMask(BitPos);
}
int _tmain(int argc, _TCHAR* argv[])
{
long data[8] = {0};
// Set bit 13
BitSet(UsingLongArray(data), 13);
wcout << "set bit 13 = " << BitGet(UsingLongArray(data), 13) << endl;
// Reset bit 13
BitReset(UsingLongArray(data), 13);
wcout << "reset bit 13 = " << BitGet(UsingLongArray(data), 13) << endl;
wcout << endl;
system("pause"); // Halts execution; shows the "Press any key to continue..." prompt
return 0;
}
It works exactly like PB with an array of LONG.
data[BitPos / 32]
This should give you better performance: The shift instruction is 30x faster than division. (the compiler might do this for you aleady if it is optimising)
data[BitPos >>5]
Charles
Thanks for the tip!
...