Search

O.3 — Bit manipulation with bitwise operators and bit masks

In the previous lesson on bitwise operators (O.2 -- Bitwise operators), we discussed how the various bitwise operators apply logical operators to each bit within the operands. Now that we understand how they function, let’s take a look at how they’re more commonly used.

Bit masks

In order to manipulate individual bits (e.g. turn them on or off), we need some way to identify the specific bits we want to manipulate. Unfortunately, the bitwise operators don’t know how to work with bit positions. Instead they work with bit masks.

A bit mask is a predefined set of bits that is used to select which specific bits will be modified by subsequent operations.

Consider a real-life case where you want to paint a window frame. If you’re not careful, you risk painting not only the window frame, but also the glass itself. You might buy some masking tape and apply it to the glass and any other parts you don’t want painted. Then when you paint, the masking tape blocks the paint from reaching anything you don’t want painted. In the end, only the non-masked parts (the parts you want painted) get painted.

A bit mask essentially performs the same function for bits -- the bit mask blocks the bitwise operators from touching bits we don’t want modified, and allows access to the ones we do want modified.

Let’s first explore how to define some simple bit masks, and then we’ll show you how to use them.

Defining bit masks in C++14

The simplest set of bit masks is to define one bit mask for each bit position. We use 0s to mask out the bits we don’t care about, and 1s to denote the bits we want modified.

Although bit masks can be literals, they’re often defined as symbolic constants so they can be given a meaningful name and easily reused.

Because C++14 supports binary literals, defining these bit masks is easy:

Now we have a set of symbolic constants that represents each bit position. We can use these to manipulate the bits (which we’ll show how to do in just a moment).

Defining bit masks in C++11 or earlier

Because C++11 doesn’t support binary literals, we have to use other methods to set the symbolic constants. There are two good methods for doing this. Less comprehensible, but more common, is to use hexadecimal. If you need a refresher on hexadecimal, please revisit lesson 4.12 -- Literals.

This can be a little hard to read. One way to make it easier is to use the left-shift operator to shift a bit into the proper location:

Testing a bit (to see if it is on or off)

Now that we have a set of bit masks, we can use these in conjunction with a bit flag variable to manipulate our bit flags.

To determine if a bit is on or off, we use bitwise AND in conjunction with the bit mask for the appropriate bit:

This prints:

bit 0 is on
bit 1 is off

Setting a bit

To set (turn on) a bit, we use bitwise OR equals (operator |=) in conjunction with the bit mask for the appropriate bit:

This prints:

bit 1 is off
bit 1 is on

We can also turn on multiple bits at the same time using Bitwise OR:

Resetting a bit

To clear a bit (turn off), we use Bitwise AND and Bitwise NOT together:

This prints:

bit 2 is on
bit 2 is off

We can turn off multiple bits at the same time:

Flipping a bit

To toggle a bit state, we use Bitwise XOR:

This prints:

bit 2 is on
bit 2 is off
bit 2 is on

We can flip multiple bits simultaneously:

Bit masks and std::bitset

std::bitset supports the full set of bitwise operators. So even though it’s easier to use the functions (test, set, reset, and flip) to modify individual bits, you can use bitwise operators and bit masks if you want.

Why would you want to? The functions only allow you to modify individual bits. The bitwise operators allow you to modify multiple bits at once.

This prints:

bit 1 is off
bit 2 is on
bit 1 is on
bit 2 is off
bit 1 is on
bit 2 is on
bit 1 is off
bit 2 is off

Making bit masks meaningful

Naming our bit masks “mask1” or “mask2” tells us what bit is being manipulated, but doesn’t give us any indication of what that bit flag is actually being used for.

A best practice is to give your bit masks useful names as a way to document the meaning of your bit flags. Here’s an example from a game we might write:

Here’s the same example implemented using std::bitset:

Two notes here: First, std::bitset doesn’t have a nice function that allows you to query bits using a bit mask. So if you want to use bit masks rather than positional indexes, you’ll have to use Bitwise AND to query bits. Second, we make use of the any() function, which returns true if any bits are set, and false otherwise to see if the bit we queried remains on or off.

When are bit flags most useful?

Astute readers may note that the above examples don’t actually save any memory. 8 booleans would normally take 8 bytes. But the above examples use 9 bytes (8 bytes to define the bit masks, and 1 bytes for the flag variable)!

Bit flags make the most sense when you have many identical flag variables. For example, in the example above, imagine that instead of having one person (me), you had 100. If you used 8 Booleans per person (one for each possible state), you’d use 800 bytes of memory. With bit flags, you’d use 8 bytes for the bit masks, and 100 bytes for the bit flag variables, for a total of 108 bytes of memory -- approximately 8 times less memory.

For most programs, the amount of memory using bit flags saved is not worth the added complexity. But in programs where there are tens of thousands or even millions of similar objects, using bit flags can reduce memory use substantially. It’s a useful optimization to have in your toolkit if you need it.

There’s another case where bit flags and bit masks can make sense. Imagine you had a function that could take any combination of 32 different options. One way to write that function would be to use 32 individual Boolean parameters:

Hopefully you’d give your parameters more descriptive names, but the point here is to show you how obnoxiously long the parameter list is.

Then when you wanted to call the function with options 10 and 32 set to true, you’d have to do so like this:

This is ridiculously difficult to read (is that option 9, 10, or 11 that’s set to true?), and also means you have to remember which parameters corresponds to which option (is setting the “edit flag” the 9th, 10th, or 11th parameter?) It may also not be very performant, as every function call has to copy 32 booleans from the caller to the function.

Instead, if you defined the function using bit flags like this:

Then you could use bit flags to pass in only the options you wanted:

Not only is this much more readable, it’s likely to be more performant as well, since it only involves 2 operations (one Bitwise OR and one parameter copy).

This is one of the reasons OpenGL, a well regarded 3d graphic library, opted to use bit flag parameters instead of many consecutive Boolean parameters.

Here’s a sample function call from OpenGL:

GL_COLOR_BUFFER_BIT and GL_DEPTH_BUFFER_BIT are bit masks defined as follows (in gl2.h):

Bit masks involving multiple bits

Although bit masks often are used to select a single bit, they can also be used to select multiple bits. Lets take a look at a slightly more complicated example where we do this.

Color display devices such as TVs and monitors are composed of millions of pixels, each of which can display a dot of color. The dot of color is composed from three beams of light: one red, one green, and one blue (RGB). By varying the intensity of the colors, any color on the color spectrum can be made. Typically, the amount of R, G, and B for a given pixel is represented by an 8-bit unsigned integer. For example, a red pixel would have R=255, G=0, B=0. A purple pixel would have R=255, G=0, B=255. A medium-grey pixel would have R=127, G=127, B=127.

When assigning color values to a pixel, in addition to R, G, and B, a 4th value called A is often used. “A” stands for “alpha”, and it controls how transparent the color is. If A=0, the color is fully transparent. If A=255, the color is opaque.

R, G, B, and A are normally stored as a single 32-bit integer, with 8 bits used for each component:

32-bit RGBA value
bits 31-24 bits 23-16 bits 15-8 bits 7-0
RRRRRRRR GGGGGGGG BBBBBBBB AAAAAAAA
red green blue alpha

The following program asks the user to enter a 32-bit hexadecimal value, and then extracts the 8-bit color values for R, G, B, and A.

This produces the output:

Enter a 32-bit RGBA color value in hexadecimal (e.g. FF7F3300): FF7F3300
Your color contains:
ff red
7f green
33 blue
0 alpha

In the above program, we use a bitwise AND to query the set of 8 bits we’re interested in, and then we right shift them into an 8-bit value so we can print them back as hex values.

Summary

Summarizing how to set, clear, toggle, and query bit flags:

To query bit states, we use bitwise AND:

To set bits (turn on), we use bitwise OR:

To clear bits (turn off), we use bitwise AND with bitwise NOT:

To flip bit states, we use bitwise XOR:

Quiz time

Question #1

Given the following program:

a) Write a line of code to set the article as viewed.

Show Solution

b) Write a line of code to check if the article was deleted.

Show Solution

c) Write a line of code to clear the article as a favorite.

Show Solution

1d) Extra credit: why are the following two lines identical?

Show Solution


O.4 -- Converting between binary and decimal
Index
O.2 -- Bitwise operators

312 comments to O.3 — Bit manipulation with bitwise operators and bit masks

  • tanuja

    hi,,
    below is my problem statement i want to help regarding its masking can you explain me that code with particular logic?

    problem statement:  

    Use the following code for this assignment.
    int _tmain(int argc, _TCHAR* argv[])
    {
         unsigned int int_var1, mask, result;
         int_var1 = 0x5A;
    }
    a) For value stored in int_var1 using bitwise AND(&) operation to only     preserve bit 6 and set all other bits to 0.    Use the mask variable as your masking variable.     Save the result in variable called result and print it.

    b) Using the negation operator(~), invert the bits in int_var1.Save the result     in variable called result and print it.

    c) Using bitwise OR (|) operations to set bit 2, while  preserving and all other
    bits in int_var1; Use the mask variable as your masking  variable. Save
    the result in variable called result and print it.

  • Ali Reza

    Hi.
    As the compiler will compare every bit of the bitmask and flags,then how does it give the result just according to the bit which is on in the bitmask.
    Thanks.

    #include <cstdint>
    #include <iostream>

    int main()
    {
        constexpr std::uint_fast8_t mask0{ 0b0000'0001 }; // represents bit 0
        constexpr std::uint_fast8_t mask1{ 0b0000'0010 }; // represents bit 1
        constexpr std::uint_fast8_t mask2{ 0b0000'0100 }; // represents bit 2
        constexpr std::uint_fast8_t mask3{ 0b0000'1000 }; // represents bit 3
        constexpr std::uint_fast8_t mask4{ 0b0001'0000 }; // represents bit 4
        constexpr std::uint_fast8_t mask5{ 0b0010'0000 }; // represents bit 5
        constexpr std::uint_fast8_t mask6{ 0b0100'0000 }; // represents bit 6
        constexpr std::uint_fast8_t mask7{ 0b1000'0000 }; // represents bit 7

        std::uint_fast8_t flags{ 0b0000'0101 }; // 8 bits in size means room for 8 flags

        std::cout << "bit 0 is " << ((flags & mask0) ? "on\n" : "off\n");
        std::cout << "bit 1 is " << ((flags & mask1) ? "on\n" : "off\n");

        return 0;
    }

  • Ali Reza

    Hi
    Great Tutorial!

    Could you please tell me how it is possible to shift some bit which was not there before to a position?
    As here 1 is being shifted to the positions 0 to 7 without being there before.
    Thanks

    constexpr std::uint_fast8_t mask0{ 1 << 0 }; // 0000 0001
    constexpr std::uint_fast8_t mask1{ 1 << 1 }; // 0000 0010
    constexpr std::uint_fast8_t mask2{ 1 << 2 }; // 0000 0100
    constexpr std::uint_fast8_t mask3{ 1 << 3 }; // 0000 1000
    constexpr std::uint_fast8_t mask4{ 1 << 4 }; // 0001 0000
    constexpr std::uint_fast8_t mask5{ 1 << 5 }; // 0010 0000
    constexpr std::uint_fast8_t mask6{ 1 << 6 }; // 0100 0000
    constexpr std::uint_fast8_t mask7{ 1 << 7 }; // 1000 0000

  • Constantine

    So the code:

    does the same as this:

    Why is that?

    • nascardriver

      No, what made you think that?

      • Constantine

        I see the difference now. Thank you.

        It won't flip a bit twice, if we accidentally add the same mask twice in the expression.

      • Constantine

        "what made you think that?"
        I thought at first that the code for flipping bits like this:

        may be written like this

        • nascardriver

          It can be written like that. The `|` is what broke it. Your original proposal of the two things doing the same is true if the masks all have disjoint bits (ie. no two masks have the same bit set to 1). In that case, Xor and Or do the same.

  • Al

    Why do cstdint.h's types need a static cast in order to print their values in your last code (the one asking for a hex RGBA color value). Aren't these type considered integers?

    I understand why the cast is needed if we define the colors as char variables (std::cout tries to print them as characters, right?), but I'm lost about why std::uint_fast8_t variables need a cast.

    • nascardriver

      Every type in C++ is made up of fundamental types (ie. char, int, float, etc.).
      If `std::uint_fast8_t` turns out to be an 8 bit int (It doesn't have to, if another integer is faster on your machine, that one will be used), it will probably be an `unsigned char`. Since `std::cout` treats `char` as characters, we need a cast.

  • Al

    I thought that, alternatively, we could use "named flags" without employing masks by defining a set of constexpr unsigned variables whose value corresponds to the position of a given flag. For example, as in the snipet

    Is this a bad idea?

    • nascardriver

      If you only ever want to operate on individual bits, that's fine. But you'll have to type a lot to get/set multiple bits at once, which is common for bit masks.

  • Skylar

    So far, everything's been very clear and easy to understand through the lessons until this one when I read the comment:

    Which, without the comment, I interpret the lack of {} to be avoiding data loss because we'd be going from pixel and redBits (both uint_fast32 so 32bits) to red (uint_fast8_t so 8bits).  But, with the comment, I don't understand how we'd be avoiding the static_cast if we're sending (red) through it anyways.
    I'm sure it's just something going over my head.

    • Alex

      Brace initialization disallows narrowing conversions. The result of our initialization expressions (e.g. (pixel & redBits) >> 24;) are 32 bits. We're putting that result into an 8-bit variable (which loses the top 24 bits -- intentionally int his case, but the compiler doesn't know that). That's a narrowing conversion.

      We can either use copy or direct initialization, where the compiler will happily do a narrowing conversion, or we can use brace initialization, but if we do that, we have to explicitly static_cast the 32-bit value to an 8-bit value so the initialization isn't narrowing any more.

  • HolzstockG

    Why can't we use decimal digits to represent bits? By logic every single number system (ex. Dec, Oct, hex) is converted by compiler to binary system so what's the deal?

    Also, unfortunately I can't right now check in visual studio if I can do that so I will ask - why in previous lesson every single sequence of bits during use of bitwise operators was set in bitset temporary variable? Can not we just do that on binary literals?

  • Cadmiral

    Hi, thank you for the tutorial!  Q: In your section and example in "Resetting a bit", I'm trying to figure out how the program came to the conclusions of on/off.  I got 0000 0100 for the first comparison, and 0000 0001 after the second.  I'm just trying to understand, first are my results correct?  second, how are they interpreted as true/false ?  Thanks!

    • nascardriver

      on means the bit 1, off means the bit is 0

      Any non-zero integer is `true`, so 0000 0100 is true, 0000 0001 is true, only 0000 0000 is `false`.

  • giang

    I don't understand why in 1 example you 8-bits variable  and binary assignment and in another example, you use 32-bits variable and hexadecimal assignment, why not binary too?. What's is the main difference between these two? And Why binary in 1 example and hexadecimal in other, what are the differences with using binary and hexadecimal in these examples because I think these are 2 very different types? Thanks very much

    • nascardriver

      We use what's needed. If we need 32 bits, eg. for a color, we use a 32 bit integer. With colors, we don't care about the exact bits, but about the values of each color component. For this, we don't need binary values.
      When we use flags, it's important to access bits individually, so we use a binary literal.

  • kavin

    In, "Bit masks and std::bitset" section i get this warning/error in line 28.
    (28,63): error C2220: the following warning is treated as an error
    (28,63): warning C4245: 'argument': conversion from 'int' to 'unsigned __int64', signed/unsigned mismatch

    {
            std::cout << "bit 1 is " << (flags.test(1) ? "on\n" : "off\n");
        std::cout << "bit 2 is " << (flags.test(2) ? "on\n" : "off\n");
        flags &= ~(mask1 | mask2); // turn bits 1 and 2 of
    }

    How do i get rid of the warning? I assume it has got to do with storing the result of ~(mask1 | mask2); being stored in flags by &= operator (or)
    constexpr std::uint_fast8_t getting converted to unsigned_int64 ? why shd it get converted into 64 bit value when we have specifically defined them to be 8 bit value?

    If i remove ~ operator and write,
    flags &= ~(mask1 | mask2);
    then the code compiles without error. I assume ~ produce a negative value . The -ve value is causing error?

    Could you explain me please how to make the code compile?

    • nascardriver

      Hi!

      This happened because we mixed `std::uint_fast8_t` and `std::bitset`. Those types are mostly compatible, but `~` and `|` caused the `std::uint_fast8_t` to be promoted to an `int`. Creating a `std::bitset` from an `int` can cause problems (Because `std::bitset` uses `unsigned` integers), so the compiler issued a warning/error.

      I replaced `std::uint_fast8_t` with `std::bitset` in the example. This gets rid of the error, thanks for pointing it out!
      There is a solution without having to change the types, but we haven't covered that yet.

  • TheDoctor

    I have another question.
    Well, this lesson is way harder than I thought.
    In the last section (bit mask involving multiple bits) you're doing this-

    Also you're storing 32 bits value in unsigned int pixel.

    Since the minimum guaranteed size of int is 2 bytes (16 bits), how are you doing all that?

    I'm sorry if this is a stupid question but I even searched last 2 comments pages and couldn't find anything related.

    • nascardriver

      Good point! The code won't compile if an `int` is less than 32 bits wide (The integer literal (0xFF000000) will be a wider type, eg. unsigned long.). I updated the lesson to use guaranteed-width types.

      • TheDoctor

        I was scratching my head with it, thanks for your prompt reply.

        One last suggestion as the whole point of bit manipulation is generally to save space using uint_least_32_t could help impart better habits to user when dealing with bit manipulation. I may be wrong and you may have better reasons for using fast version, and in that case, I beg your pardon.

  • TheDoctor

    Above code gives "error: negative integer implicitly coverted to unsigned type"
    I scanned through comments for possible solution and found a similar problem but couldn't understand it properly.

    • TheDoctor

      So this is what I thought of, changing line 3 of above code to this solves it,

      Here are my thoughts;
      - mask2_char was originally as expected an unsigned char type
      - ~ operator implicitly typecasts it to int
      - this int is then tried to type cast into unsigned char by &= operator with which compiler is unhappy as this implicit typecast (int to unsigned char) could lead to data loss.

      Above para is all hypothesis as I'm also just a learner, it would be nice if someone would correct or approve it.

      But I still have one question since var_bit is type std::bitset<4>, is it also first typecasted to unsigned char by &= operator (to do operation with the other unsigned char operand on right hand) and again typecasted back to std::bitset<4>?

      • nascardriver

        Your explanation is correct, only the reason for the error is different. The compiler doesn't complain about a narrowing conversion, it complains about the loss of the sign.

        ~0b0100 = 0b1011 (assuming a 4 bit int)
        The first bit is set, which means that the integer is negative. The negative `int` is then converted to an `unsigned long long` (More about this type later) by `&=`.
        The `unsigned long long` can't represent negative numbers, so you get a warning (or error).
        The compiler is able to know that the number is negative, because you made `mask2_char` `constexpr`. The compiler performs the negation at compile-time and catches the error before anything bad can happen at run-time. Without `constexpr`, you might not have noticed.

        `std::bitset` is a custom type, it doesn't follow the same rules as built-in types. It doesn't undergo integral promotion (conversion to int) when you use it with arithmetic operators. The right side of its operators (eg. `&=`) has to be a `std::bitset` as well. `std::bitset`s are created from `unsigned long long`s. You gave it an `int`, so the `int` has to be converted to `unsigned long long` and then to `std::bitset` before it can be used with `&=`. This happens automatically.

        If there's anything you didn't understand, don't hesitate to ask.

        • TheDoctor

          Yes, now I'm starting to get the hang of it, you're awesome, man.
          a.) By 'unsigned long long' you mean 'unsigned long long int', right?
          So &= operator converts what on the right to first 'unsigned long long' and then to std::bitset.
          b.) Is that why in the following code line 3 works and line 4 don't?

          • nascardriver

            a)
            Correct. Just like with `short` or `long`, the `int` can (and usually is) be omitted.

            b)
            Ignoring the wild semicolon, this doesn't work because of a concept that is covered later in the tutorials. In case you're coming back to this question later,
            `operator|=` is a member function. When you use it, there's no template deduction, because the type is already known from the left operand.
            `operator|` is a non-member template function. Implicit conversions aren't considered during template deduction, so both operands (left and right) have to be the same. `std::bitset<4>` is not the same as `unsigned char`, so no matching `operator|` is found.

            • TheDoctor

              Ah, sorry for that wild semicolon, it was a typo.
              I'll come back later after covering further sections.
              As usual, your help has been very helpful.

      • Yan Tan Yan

        Hello, may I ask what's the difference between this and using the corresponding test, set, reset, flip, functions?

  • Charan

    I read the comments and saw that char is used to define the mask because char is of size 8. If our inputs deal with higher sized values(eg: there are 12 qualities like happy,laughing... ), is it that we need to define the mask with int or long?

    • nascardriver

      You'd need a wider type, yes. Rather than using the built-in types (int, long), you should use a type with guaranteed width, eg. `std::int_fast16_t` from lesson 4.6.

      • Charan

        Thanks for a quick reply:).  I think it will be useful to add why we used char there to avoid confusion. I did not really get two char variables can be or,and,not operated  before looking at the comments .

      • koe

        Since it is somewhat ambiguous whether an int like 'std::int_fast16_t' will actually be 16 bits (it might be 32 bits), would you recommend favoring 'std::bitset<16>' to guarantee it's 16 bits every time? The integers with guaranteed size, like int32_t, we were told not to use since they may not be supported on all architectures.

  • Anderson

    Hi!

    You know when we configure our character output to print out hexadecimal or binary figures like this:

    How exactly do we tell the compiler to exit the hexadecimal output mode ?

    Thanks.

  • Anderson

    Hi!

    Is it possible to create flags with binary digits using C++ 11 or prior
    like this ?

    instead of using hexadecimal digits for the flag value.

    • nascardriver

      You can write a `constexpr` function that converts a binary string to a binary number. I'm sure there are plenty of examples for this on the internet.
      You don't need binary literals though, set up your flags and use bitwise arithmetic instead.

      • Anderson

        Thank you nascardriver.

        I understand you could use bitwise arithmetic to form binary values as an alternative to using binary numbers. But what if I wanted to represent something like " 0b0101'0000 " (notice the multiple 1's) in bitwise arithmetic.

        Do you think I can do something like this ?:

        Thank you once more.

        • nascardriver

          Please edit your comments instead of deleting and re-posting them. Code tags work after refreshing the page.

          If you're working with flags, you'll only have single bit flags. As I showed above, you can use a bitwise or to combine flags.
          Your example doesn't work, `101` is a decimal number. You can use a decimal `5` (Binary 101) and shift left by 4, or set the value bit by bit

  • Hana

    Do you have a chapter on bit fields?

  • Jim

    Hi, Alex or nascar
    I have a question, why do we need to use bit masks in the program that extracts RGB colors from a hexadecimal value, when it can be done like this:

    • nascardriver

      Hi Jim

      There are several ways of extracting the individual values from an rgba number. I like yours, although it requires the reader to know how the conversion from `unsigned int` to `unsigned char` works. There are also purely arithmetic solutions, eg.

      Since those solutions, including yours, defeat the purpose of the code in the lesson, which is to teach bitwise operations, I'll leave the lesson as is.

  • Louis Cloete

    Hi Alex!

    Shouldn't the bit masks be declared constexpr rather than const?

  • avidlearner

    There might be a slight error on "Setting a bit" line 18: should be mask1, not mask4.

  • Pablo Asenjo Navas-Parejo

    Hi Alex or Nascar. Could you tell me why does this happen? If I initialize @eightflags to @mask3 and then I assing @eightflags the value of @eightflags & @mask3, it equals false, but if I assing @eighflags the value of @mask3 & @mask3, it equals true. I think this shouldn't happen since @eightflags is supposed to be equal to @mask3.

    Code:

    Thank you!

  • Vishal

    Hey Alex, I  learn C,  C++,  Java,  HTML,  CSS3,  javascript,  python.  I almost understand all programming concepts of these modern programming languages but until now I don't build any cool stuff. I don't know what to do when I learn some new language. Alex please give me some suggestions to how I make or create some great stuff and what should I do when  I learne some new programming language.

    • Hey Vishal, I've found this website (https://www.linuxtrainingacademy.com/projects/) particularly useful as a wellspring of ideas for things to try out when you learn a new programming language.  The links within suggest everything from simple manipulation programs to complex and massive projects, so I'm sure there will be something for every level of experience and comfort.  The projects are almost all language-agnostic too, so you might even challenge your skills by trying to code the same thing in many of the languages you mentioned.  Happy coding, and welcome to the community!

  • Grego

    Hello Alex & Nascardriver,

    This may be a stupid question, but why are contants in this lesson assigned to and not initialized?
    I looked back to char variables and constants lessons and could see both of them showing proper initialization.
    What makes this type of a constant not need an initialisation? Am I just missing something obvious?

    • Alex

      These lessons are still in the process of being rewritten/updated, so they aren't yet compliant with all modern best practices. The constants here are being initialized (not assigned) via copy initialization rather than the now-preferred uniform/brace initialization.

  • learning

    what's wrong with this code? gives a warning:

    • is an `int`, `red` is a `char`. Converting from `int` to `char` could cause data loss. You're doing it on purpose and know that you're not losing data. Add a cast to silence the warning.

  • Sagar Pohekar

    Hello,
    Thanks for the tutorial.
    BTW, you said you are in process of replacing compile time/symbolic constants from 'const' to 'constexpr', so this tutorial is good place to use 'constexpr'

    Thanks.

  • Alireza

    Hello and thank you so much for the Bit flags tutorial. This is very useful.

    question: Why have you used a char variable to use bit flags, Why haven't you used a bool variable or other ones to teach bit flags ?
    Does it mean especial ?

    Why the following program gives errors ?

    Imagine I write this program, which variable does bitset do ?

    • Alex

      std::bitset functions take bit positions, not bit masks. o1 works because it evaluates to bit 2, o2 works because it evaluates to bit 4, but o3 doesn't work because it evaluates to bit 8, which is out of range for a bitset of size 8.

      • Alireza

        Thanks for replying,
        So the inputed number in std::bitset as the size is not bits' number ; it is their values and must be equal to our flags.

        Sorry but you haven't answered it yet:

        Why have you used a char variable to use bit flags, Why haven't you used a bool variable or other ones to teach bit flags ?

        and one more question (important):

        Even though the value 128 is equal to 1000 0000 in binary, and 255 is equal to 1111 1111 in binary, so what's difference between std::bitset<128> and std::bitset<255> ?

        • Alex

          > So the inputed number in std::bitset as the size is not bits' number ; it is their values and must be equal to our flags.

          I read this a bunch of times and I'm not sure what you're trying to say.

          This line defines a std::bitset with a size of 8 bits, and initializes those bits to 0b'0000'0010. This is fine.

          This is invalid, as o2 is decimal value 8, and 8 is outside the range of our bitset. You actually meant:

          I use a char here because I want 8 bits, and unsigned because we should always use unsigned variables when dealing with bits. Bool is typically used for logical operations, not bitwise operations. It's bad practice to use bool in a bitwise context. I'm also not sure how well defined it is for use with bitwise operations.

          std::bitset<128> should define a bit field that holds 128 bits, and std::bitset<256> should define a bit field that holds 256 bits.

  • a700

    Hi, can you explain how this goes?
    if (myflags & option4)
        std::cout << "myflags has option 4 set";

    • bitwise-ands myflags with ...10000, ie. the result is all 0, and the fifth bit from the right is the same as in @myflags.
      If @myflags doesn't have this bit set, the result is 0.
      Non-zero integers evaluate to true, 0 evaluates to false.
      If the fifth bit from the right is set in @myflags, the condition is true.

  • Senna

    Hi,
    Why this webpage is broken down these days ?
    Is it temporary ?
    Don't stop supporting it, please.
    There's no source as simple, full contents as like learncpp.

    • Hi Senna!

      Quoting the index: "Feb 15: [Site News] Our server died yesterday and had to be restored from backups. We’re in the process of getting everything restored and reconfigured. If you find anything broken, please let us know here. Sorry for the inconvenience."

      If you want to continue reading while learncpp is down, you can do so on archive.org
      http://web.archive.org/web/20190214123506/https://www.learncpp.com/

    • Alex

      Yup, there was a hardware failure on the server. The site has been moved to a new server and should be up and running full-time (at least, until the next catastrophe). :)

Leave a Comment

Put all code inside code tags: [code]your code here[/code]