c/c++位运算妙用

  在vc++编程中,会发现微软的不少API里面都用到了位运算,好比这个函数:c++

CreateWindowExA(
    __in DWORD dwExStyle,
    __in_opt LPCSTR lpClassName,
    __in_opt LPCSTR lpWindowName,
    __in DWORD dwStyle,
    __in int X,
    __in int Y,
    __in int nWidth,
    __in int nHeight,
    __in_opt HWND hWndParent,
    __in_opt HMENU hMenu,
    __in_opt HINSTANCE hInstance,
    __in_opt LPVOID lpParam);

这是windows API里面建立窗口的函数,第四个参数dwStyle,表示窗口风格,窗口风格固然会有不少种, 并且不少种之间也是能够组合的,那么到底怎么样用一个参数表示这么多中风格以及这些风格之间的组合呢?注意到了在写程序的时候这个参数常常是这样的:编程

WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU ,很明显这个参数能用或运算组合在一块儿,咱们在VS中右击转到定义, 发现WS_CAPTION这些宏其实都是一个16进制的数字, 是如WS_CATION, 跟踪发现WS_CAPTION实际上是WS_BORDER和WS_DLGFRAME或运算结果,WS_BORDER = 0x00800000L,WS_BORDER,dwStyle这个参数归根接地都是由WS_BORDER这样最基本的风格位运算组合的。windows

  windows中DWORD为32位,咱们仔细研究发现, 每种最基本的窗口风格如WS_BORDERz换换成二进制为100000000000000000000000,发现其32位中只有一位为1, 对应其余风格也都相似只有一位为1。假如窗口风格有32种(固然没那么多),那么dwStyle参数32位的每一位对应一种风格, 这一位为1就有这个风格, 为0 就没这个风格,这样咱们就能经过位运算将不一样的风格组合在一块儿或者去掉某种风格。在建立窗口的时候只须要解析出dwStyle对应的每一位是否为1咱们就能知道是否要包含这种风格。说了这么多来看看个人代码吧:函数

//判断DWORD对应位是否为1
//b为须要判断的数, i为对应的位数
BOOL TestDword(DWORD b, DWORD i)
{
    ATLASSERT(i <= 31); 
    return (b&(0x01<<i))==0?FALSE:TRUE;
}


//将某一位置为1或者0
//p为须要改变的数的指针,i为须要置0的位数
//state为0或者1,
//其也只能为0或1(二进制每一位不是0就是1) void SetDWBit(DWORD* p, int i, DWORD state) { ATLASSERT(i <= 31 && (state == 0 || state == 1)); if (state == 0) *p &= ~(0x01<<i); else *p |= 0x01<<i; }

上文中个人代码由于是在ATL下写的因此用的ATLASSERT,你们没有使用ATL的能够本身改掉。注意到函数中我都是用0x01移位操做的。TestDword判断某一位是否为1, SetDwBit将对应的某一位置为0 或者1。有了这两个函数咱们就能很方便的在本身的代码中使用位运算。好比咱们能够用一个DWORD(32位)型变量表示某个对象对应的是否有32个状态,注意此处个人第二个参数是位数是对应0到31的因此须要0x01<<i这个操做, 当让咱们也能够像windows同样定义出每种风格 0x00000001(0x01<<0),0x00000010(0x01<<1),0x00000100(0x01<<2)...,上面函数只须要稍改下就好。spa

  不少时候咱们均可以用一个变量表示不少种状态,而不须要为每种状态定义一个变量,这样咱们的程序会更简洁更高效。以上函数用到位运算,若是不熟悉位运算的能够本身查资料。有什么错误请你们指出。指针

相关文章
相关标签/搜索