0

Suppose I have a decimal number 1033 how do I get the bits from 0 to 9 (in this case it will be 9 decimal) and how do I get the bits from 10th bit to 15th bit in this case it will be (1 decimal). Is there an option in C++ that could assist me in accomplishing this and how to use it. Thanks in advance

MistyD
  • 16,373
  • 40
  • 138
  • 240
  • Boolean arithmetic operators and specifying constants in hex helps with this. `b = 1033 & 0x3FF;` – Richard Mar 02 '19 at 19:11
  • @Richard can you please explain a little bit on how i can use boolean arithmetic here – MistyD Mar 02 '19 at 19:12
  • You could shift the number by x, and then use a mask to access just the low bits of interest. – Eljay Mar 02 '19 at 19:13
  • In this contex the `&` is a bitwise and operation. So each bit in the result is the the result of the and operation of two corresponding input bits. The truth table for and is `0 & 0 = 0`, `0 & 1 = 0`, `1 & 0 = 0`, `1 & 1 = 1`. You want to mask off bits 0 through 9 so you and the value you want to operate on (1033) with a value that has all those bits set to 1, which would be `1023` or in hex notation `0x3FF`. By the way 1033 with all but bits 0 to 9 stripped off is 9 not 1. – Richard Mar 02 '19 at 19:16
  • The argument that this question is a duplicate would be valid if the other question was about C++. That question was asked, and all but one of the answers posted, more than 5 years ago; it is not tagged with a language, and the OP is asking about C. C++ is a different language from C, and C++ today different from 5 years ago. While C idioms can be used in C++, C++ often has better ways to solve the problem. My answer would be inappropriate if added to the other as it would not compile as C. How does one ask questions about languages which have idioms not supported by a C compiler? – Richard Mar 03 '19 at 13:15

1 Answers1

0

So it appears I misread your question, which is why I don't like using comments, and that after a few minutes you can't correct them. But I have been warned off posting answers to questions of this sort but never the less here is a basic example:

#include <iostream>
#include <iomanip>
#include <stdexcept>
#include <type_traits>

template<typename UnsignedType>

UnsignedType mask(UnsignedType value, size_t low_bit, size_t high_bit) {
    static_assert(std::is_unsigned_v<UnsignedType>, "UnsignedType must be an unsigned type.");
    if (low_bit <= high_bit && high_bit < std::numeric_limits<UnsignedType>::digits) {
        UnsignedType mh = (1 << (high_bit+1)) - 1;
        UnsignedType ml = (1 << (low_bit)) - 1;
        UnsignedType mask = mh & (~ml);
        std::cout << "Mask     " << std::hex << mask << '\n';
        return value & mask;
    } else {
        throw std::logic_error("Bit range error.");
    }
}

int main() {
    auto r1 = mask<uint32_t>(1033, 0, 9);
    std::cout << "Result 1 " << r1 << '\n';
    auto r2 = mask<uint32_t>(1033, 10, 15) >> 10; // Also shift right to zero base the result.
    std::cout << "Result 2 " << r2 << '\n';
    return 0;
}

If you are only using a small number of bit offsets known at compile time you can take advantage of that:

#include <iostream>
#include <iomanip>
#include <stdexcept>
#include <type_traits>

template<typename UnsignedType, size_t LowBit, size_t HighBit>

UnsignedType mask2(UnsignedType value) {
    static_assert(std::is_unsigned_v<UnsignedType>, "UnsignedType must be an unsigned type.");
    static_assert((LowBit <= HighBit) && (HighBit < std::numeric_limits<UnsignedType>::digits),
                  "Bit range error");
    constexpr UnsignedType mh = (1 << (HighBit + 1)) - 1;
    constexpr UnsignedType ml = (1 << (LowBit)) - 1;
    constexpr UnsignedType mask = mh & (~ml);
    std::cout << "Mask     " << std::hex << mask << '\n';
    return value & mask;
}

int main() {
    auto r1 = mask2<uint32_t,0,9>(1033);
    std::cout << "Result 1 " << r1 << '\n';
    auto r2 = mask2<uint32_t,10,15>(1033) >> 10; // Also shift right to zero base the result.
    std::cout << "Result 2 " << r2 << '\n';
    return 0;
}
Richard
  • 8,920
  • 2
  • 18
  • 24