C++ 二维 Bit Map

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;

class BitArray2D
{
private:
    int mRow, mCol;
    unsigned char **A, *B;
    bool isValid(int row, int col)
    {
        return row > 0 && col > 0 && row <= mRow && col <= mCol;
    }

public:
    BitArray2D(const int &row, const int &col) : mRow(row), mCol(col)
    {
        if(!isValid(row, col))
            std::cerr << "parameter error." << std::endl;

        int i, j;
        int r = row;
        int c = (col%8 == 0) ? col/8 : col/8 + 1;

        A = new unsigned char *[r]();
        B = new unsigned char[r*c]();

        for(i=0,j=0; i < r; i++)
        {
            A[i] = &B[j];
            j += c;
        }
    }

    ~BitArray2D()
    {
        delete B;
        delete []A;
    }

    bool bitGet(int row, int col)
    {
        if(!isValid(row, col))
            return false;
        return A[row][col >> 1] & (1 << col);
    }

    void setOne(int row, int col)
    {
        if(!isValid(row, col))
            return;
        A[row][col >> 1] |= (1 << col);
    }

    void setZero(int row, int col)
    {
        if(!isValid(row, col))
            return;
        A[row][col >> 1] &= ~(1 << col);
    }
};


int main()
{
    BitArray2D ba(3,4);
    ba.setOne(1,2);
    int i,j;
    for(i = 0; i < 3; i++)
    {
        for(j = 0; j < 4; j++)
        {
            std::cout << ba.bitGet(i,j) << " ";
        }
        std::cout << std::endl;
    }
    std::cout << ba.bitGet(1,2) << std::endl;
}

 想尽各种办法实现[][]的重载都失败了。只好用()替代。使用起来也还行。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*
 *  1. clear
 *  2. setOne/Zero
 *  3. get
*/
#define SHIFT 5  // 32 = 2^5
#define MASK  0x1f        // 0001 1111    5bits [0,31]
void bitSetOne(int *A, int idx)
{
    int *pA = A;
    // idx>>5即idx/32      1 left shift [0,31]
    // p[0] = p[0] | 000001000                              idx & MASK即截取idx有效的范围(0~2^5),实际上改成判断更合适,最后取或运算设置进去。相当于取模的运算
    pA[idx >> 5] |= (1 << (idx & MASK));                    // 1左移这么多位,设置进去。在内存中,实际上的存储顺序还是从每个int的低位到高位,只不过读取的过程中经过了计算,对外就像是连续的
}
void bitSetZero(int *A, int idx)
{
    int *pA = A;
    pA[idx >> 5] &= ~(1 << (idx & MASK));
}

int bitGet(int *A, int idx)
{
    int *pA = A;
    return pA[idx >> 5] & (1 << (idx & MASK));
}

#include <stdlib.h>

int main()
{
    const int N = 100;     // 100 bits

    int A[1+N/32];         // size = 4  32 bits
    memset(A, 0, sizeof(A));
    bitSetOne(A, 1);
    bitSetOne(A, 3); 
    printf("%d\n", A[0]);

    if(bitGet(A, 0)) printf("1"); else printf("0"); 
    if(bitGet(A, 1)) printf("1"); else printf("0"); 
    if(bitGet(A, 2)) printf("1"); else printf("0"); 
    if(bitGet(A, 3)) printf("1"); else printf("0"); puts("");

    bitSetZero(A, 1);
    if(bitGet(A, 1)) printf("1"); else printf("0"); puts("");
}

 注意

1 逻辑右移和算术右移

逻辑右移,移走的位填充为0;算术右移,移走的位填充与符号位有关,例如如果为负数,则移走的位填充为1。

2 unsigned int 和 int

C语言的标准指出,无符号数执行的所有移位操作都是逻辑的,而对于有符号数,采用哪种方式取决于编译器。算术左移和逻辑左移是相同的,而算术右移和逻辑右移,取决于符号位。因此,一个程序如果使用了有符号数,是不可移植的。嵌入式的程序通常采用交叉编译开发,如果定义为有符号的,就无法保证右移操作能跨平台使用,这就是为什么用unsigned int,而不用int的主要原因。

 

原文链接: https://www.cnblogs.com/abnk/p/12780507.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    C++ 二维 Bit Map

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/344506

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午2:44
下一篇 2023年3月2日 上午2:44

相关推荐