std::bitset是C++标准库中的一个类,用于表示和操作由固定数量的位组成的二进制序列。
以下是三种获取 std::bitset 对象中从某一位到另一位的值,并以十进制形式输出的方法:
主要区别就是获取掩码的方式。

方法一

std::bitset<8> binary("10101010"); // 假设有一个8位的二进制数
    int start = 2;
    int end = 5;

    // 创建掩码
    std::bitset<8> mask = (1 << (end - start + 1)) - 1;
    std::cout << mask << std::endl;

    // 提取目标位
    std::bitset<8> extracted = binary & (mask << start);
    std::cout << extracted << std::endl;
    // 右偏移
    extracted >>= start;

    // 输出结果
    unsigned long decimalValue = extracted.to_ulong();
    std::cout << decimalValue << std::endl;

在上述示例中,创建了一个 std::bitset 对象 binary,表示一个8位的二进制数。
然后,定义了起始位和结束位的索引,即 start 和 end。
创建了一个掩码 mask,并将其移位并减一得到。
然后,使用按位与运算符 & 将 binary 与 (mask << start) 进行按位与运算,以提取目标位。
通过右移 extracted 得到结果,最后将其转换为十进制数并输出。
(1 << (end - start + 1)) - 1解释
(1 << (end - start + 1)) - 1 是用于创建掩码的表达式,其含义是:

  • << 是位移运算符,表示将位向左移动指定的位数。
  • end - start + 1 表示要提取的位数(即结束位减去起始位再加1),例如 end 为5,start 为2,那么end - start + 1 的结果就是4,表示要提取4位。
  • (1 << (end - start + 1)) 将数字1左移指定的位数,在这里就是将1左移4位,结果为16(二进制表示为 10000)。
  • - 1 将上一步的结果减1,就是将全部位都置为1,得到最终的掩码,例如 16 - 1 的结果就是 15(二进制表示为 1111)。

这样,通过这个表达式得到的掩码中,除了想要提取的位为1,其他位都为0。这样再与要提取的位进行按位与运算,就可以将想要的位提取出来,并清零其他位。
美不美?

方法二

std::bitset<8> binary("10101010"); // 假设有一个8位的二进制数
    int start = 2;
    int end = 5;

    // 创建掩码
    std::bitset<8> mask = (1<<(end+1)) - (1<<start);//(1 << (end - start + 1)) - 1;
    std::cout << mask << std::endl;

    // 提取目标位
    std::bitset<8> extracted = binary & mask;// (mask << start);
    std::cout << extracted << std::endl;
    // 右偏移,得到的结果从0位开始
    extracted >>= start;

    // 输出结果
    unsigned long decimalValue = extracted.to_ulong();
    std::cout << decimalValue << std::endl;

(1<<(end+1)) - (1<<start) 是一个表达式,用于创建一个掩码,其含义是:

  • << 是位移运算符,表示将位向左移动指定的位数。
  • end+1 表示结束位的索引加1,这样可以将要提取的位的下一位(即结束位的下一位)设置为1。例如,如果结束位是5,那么 end+1 的结果就是6。
  • (1<<(end+1)) 将数字1左移指定的位数,在这里就是将1左移6位,结果为64(二进制表示为 1000000)。

同时,也需要创建一个表示起始位的掩码,用于将起始位到最高位的位全部置为0,并将起始位和之前的位全部置为1。这里使用 (1<<start) 来创建起始位掩码,例如,如果起始位是2,那么 (1<<start) 的结果就是4(二进制表示为 100)。

最终,将结束位的掩码与起始位的掩码进行减法操作,得到最终的掩码。

例如,如果结束位是5,起始位是2,那么 (1<<(end+1)) - (1<<start) 的结果就是 60(二进制表示为 111100)。

这样,通过这个表达式得到的掩码中,除了想要提的位为1,其他位都为0。这样再与要提取的位进行按位与运算,就可以将想要的位提取出来,并清零其他位。
美不美?

方法三

std::bitset<8> binary("10101010"); // 假设有一个8位的二进制数
        int start = 2;
        int end = 5;

        // 创建掩码
        std::bitset<8> mask;
        // 注意,bitset的下标是从0开始的
        for(int i = start; i < end+1; ++i) {
            mask.set(i, true);
        }
        //std::bitset<8> mask = (1<<(end+1)) - (1<<start);//(1 << (end - start + 1)) - 1;
        std::cout << mask << std::endl;

        // 提取目标位
        std::bitset<8> extracted = binary & mask;// (mask << start);
        std::cout << extracted << std::endl;
        // 右偏移
        extracted >>= start;

        // 输出结果
        unsigned long decimalValue = extracted.to_ulong();
        std::cout << decimalValue << std::endl;

上述示例创建掩码,就很明确,直接复制,之后做&运行,然后有偏移得到最终结果。
美不美?