Hello, and welcome. Let's talk about bitwise operators.
We showed you a little glimpse of this in the previous lecture when we talked about assignment operators
because assignment operators have all these compound assignments where you can
perform an operation like an addition and then also assign.
You can do the same things with these type operators.
But let's go into these more detail and exactly tell you what they are.
So c offers bitwise logical operators
and shift operators. Those terms might be completely clueless on.
They look like logical operators, but they're quite different. They don't do any
kind of Boolean evaluations. They don't evaluate true or false.
They look like the ampersand ampersand, the 2 ors,
but they're not doing any kind of Boolean evaluation.
What they're doing is they're operating on bits, inside integer values.
And so you may ask yourself why the heck would you ever want to do this? Well,
it's not used in most programs. It's more of an advanced technique.
Even though this is a beginner class. They are part of the operators, and operators are a beginner concept.
So I'm going to address them, but we're going to not necessarily focus on them.
I'll give you some examples, show you how you can use them.
But you're not going to be an expert in this after this lecture.
But the way that they're useful and why you'd actually want to use them
is because you can store quite a bit of data.
So there's bitwise operands called and, ampersand and the bitwise or
which is an or just a single parallel bar.
Try not to get these confused again with the logical operators.
Logical operators have 2 of them, ampersand ampersand, which is an and.
The bitwise operators just have a single. So just an ampersand or just an or.
And so what they're going to do is they're going to test and they're going to set individual bits
inside of an integer variable. What is a bit?
We know a bit is a way to measure data.
But a bit is essentially just a 0 or 1 value.
And 8 of those make up a byte. So a bit is a 0 or 1.
And what you can do is an integer,
remember, depending on the system you're running could, it could be 8 bytes.
And so you could turn on and off each bit.
And when I say turn on or off, I'm saying you can either have them be equal to 1 or 0.
And then you can use those bits to tell you something.
So you can store a lot of data by having bits represent some kind of data.
That's why one of the reasons why the computer uses
bits in 1 and 0s and binary numbers to do operations
because you can store a lot of data. Now
exactly what this means is here's an example. You could use a single integer variable.
Again, an integer is a number, an integer represents
4 to 8 bytes depending on what system you're running.
That means if there's 4 bytes that means there's 32 bits.
There's 32 0s or 1 values.
So you can use all those bits to represent something.
So for example if you want to store individual characters a person,
you could just have 1 bit, tell you whether or not
the person is male or female by saying 1 is equal to male 0 is equal to female.
You just either turn it on or turn it off.
Then you could use 3
bits to specify whether the person can speak French, German or Italian.
So the 1 bit could represent French. If it's not 1
0, then that means they don't speak French.
If German is 0 that means they don't speak German.
If it's 1, it means they do speak German. So by turning off and on these bits,
setting them 1 to 0, you can represent a lot of data.
You could have another bit to record whether the person's salary is 50,000 or more.
If it's 1, it's true, yes, it is. 0 false.
So basically we just specified here.
It actually says 4, but we actually specified 5 bits of data,
only 5 out of whether or not we have
32 or if we have 64 bits, but we only used 5
and we able to represent whether or not a person is female or male,
whether or not they speak French, German or Italian or all 3 or one or the other.
And whether or not they're making more than $50,000.
We can represent all that data in our bits.
And this is where the bitwise operators come in handy.
Now that we know how we can use bits to store a lot
of different data. Let's talk about those binary numbers.
We know that a binary number is just a number that includes 1s and 0s.
And that's why it's advantageous to use. Bit operators in an integer,
the number can be of any length.
The following are examples of binary numbers, just 0s and 1s.
So you've seen this 0 1 0 1 0 1 1 0 1 0 1 0.
And remember that a byte is 8 bits.
An integer is usually 4 bytes on most platforms.
It depends on the architecture, but mostly 32 bits.
So you have 32 values that you can store with 1s and 0s to indicate on or off.
Binary numbers, again every binary number has a corresponding decimal value,
so you need to understand how to convert binary to decimal.
Examples here 1 is equal to 1, 1 0 is 2, 1 1 is 3,
these are simple conversions.
Again, usually they have more bits, 1 0 1 0 1 1 1.
The way that you want to convert the binaries numbers to a
decimal number is you want to look each position
in the byte with the bit corresponding bit and then use the power of 2.
So for each digit you multiply the digit by its position value
using the power of 2. And then you add up the entire project to get the final result.
So position values and a binary number are the powers of 2.
So the first position would be the value
2 0, which, in other words, would be 1.
And then the second position would be the value of 2 to the first power which is 2,
2 to the 2 would be 4, 2 to 3 would be 8,
2 to the 4 would be 16. And you keep doing that over
and over again. And so it's easier to understand if you see a nice example.
And so here we have a binary number of 0 1 1 0 1 0 0 1.
The decimal equivalent of that is 105.
The way you convert is you start on the right-hand side for each bit
and you multiply to the power of 2 depending on if the bit is 0 1.
So if we start all the way to the right, we have 1.
So we say 1 times 1 and we keep that 1. Then the next 1,
the second position is 0 times 2 0. Then 0 times 4,
1 times 8, 0 times 16,1 times 32,
1 times 64 and 0 times 28.
And you add all those up, and you get the result of 105.
That's 1 way to convert. You can actually convert it left to right as well
by multiplying by 2 and then adding
1 or adding 0 depending on what the next bit is. So for example,
you can also if you go left to right,
you start off with 1 because 0 doesn't matter.
So the second bit going from the left to right, you have 1.
The third bit, you have 1 times 2
plus 1, so you have 3.
And again, you multiply by 2 so you say 3 times 2 plus 0 which is 6.
6 times 2 plus 1, which is 13.
13 times 2 is 26.
26 times 2 is 52
times 2, which is 104 plus 1.
So again multiply by 2 and then add 1. Another example,
again, the right to left is usually a little bit easier.
Here's 1 0 0 1 1 1 0 0.
And that converts to 156 because you say again 0 times 1,
0 times 2, 1 times 4, 1 times 8, 1 times 16 and so forth
and then you add all them together,
which is 4 8 12 16 28 plus 128 is 156.
And again, if you go left to right you multiply by 2 add 1.
So we started for 1. Say 1
2 4
9, 4 times 2 plus 1,
9 times 2 is 18 plus 1 is 19 times 2,
38 plus 1 is 39 times 2 which is 78
times 2 which is 156.
So this is a quick demonstration of how you can convert
binary to decimal. Now converting decibel into binary,
I usually just use a conversion on the web
if you're really interested in that. But you can take these binary numbers and then perform bitwise operators
So let's take a look at the bitwise operators.
So the bitwise operators are summarized here. And again, another nice table I got
online, but they look similar to logical operators. But again, don't confuse them.
So the ampersand by itself is a binary and operator.
And so what this is doing is it's copying a bit to the result
if it exists in both operands. So if both of them are true,
then it's going to copy a bit.
So if a and b is equal to 12,
you're going to have a binary representation of 0 0 0 0 1 1 0 0.
So a and b would be
that number. We'll go through some examples.
A binary or copies a bit if it exists in either operand
so a or b
will copy a bit if it exists in either operand. So if either operand
is equal to 1, it will copy a bit.
And then the binary xor, this is the exclusive or.
This will copy the bit if it is set in 1 operand but not both.
So if you have a true, but only 1 true
and you use the carrot to represent this on your keyboard,then it's going to
it's going to copy a bit and it's going to say it's
true,
binary 1s complement.
So again, we're getting the binary data here because we're talking about bits. So hopefully,
1's complement.
Operator is unary and has the effect of flipping the bits,
basically just negating and taking the monitor off.
So an example here was if you say tilde a,
you're applying the 1s complement operator.
And if it's equal to negative 61, it will be 1 1 0 0 0 0 1.
So if you were to actually convert that binary number to decimal
which is negative number and
the first number is the sign. So 1 tells you that it's a sign.
And then you say 1 2 4 8 16 33
and then 61, so that's how it would be represented.
So I'll go through more concrete examples of this.
But basically, if you have a binary number, a is initially a binary number that's 0 0 1 1 1 1 0 0
which is 60 and you supply the flipping
basically it's going to then turn into negative 61,
which is 1 1 0 0 0 0 0 0 0 0 0 1 1.
So this is the results of variables that are actually set. So again,
I'm assuming that a has certain binary representation and b has a certain binary representation.
So if a is equal to, again, 60 and b is equal to 13,
then the result of adding them together doing a bitwise and
is going to be 0000 11 00, which is 12.
Again, I'll go through these examples but this is trying to provide a little
description of these different binary operators.
The less than less than symbol is going to shift bits to the left.
So the left operand value is moved left by the number of bits specified by the white operand.
So if you do something like a
less than less than 2
and a is actually equal to you know some binary number,
for example, 0 0 1 1 1 1 0 0,
you're going to shift the bytes by 2.
So you're going to take off the 0s and it's going to become 1 1 1 1, and those 0s are going to go to the end.
And the same with the right shift operator. You're just shifting them to the right as opposed to the left.
Here you use the greater than symbols.
And so I'm going to go through these in a second.
The other important thing to understand with the bitwise operators
is how to evaluate these a and b values. So
what does a 1 and a 1 evaluate to a 1,
if it's an ampersand. If it's an or 1 and 1
evaluates to 1 as well.
But a 1 and 1 and a 0 if you're using an ampersand
doing an and, that evaluates to 0 false. So I just wanted to provide a little truth table here
that shows you the values when you're doing it,
you use an and an or an exclusive or.
So here if you have p0 and q0, which means they're both false
and you apply an and,
it's going to be false because they both have to be true for that to be true.
And that's what you see in row 3.
They're both true then p and q is going to evaluate to 1, true.
If they're not both true, it's always false.
P or q only 1 of them needs to be true.
So that's why you see rows 1 and rows 2 equal to 1 and row 3 equal to 1.
The only time it's false is when they're both false.
And then the exclusive or is at least 1 of them
is true, and only 1.
So if p is false and q is true, it will return true.
And if p is true and q is false, it will return 1.
So this gives you an idea of how it's evaluated.
Again, a lot of math stuff, but when we talk about binary digits, that's what we're talking about.
So let's look at some concrete examples and code blocks. Hopefully, this will help a bit.
So here's our function. I'm going to create a couple more variables.
I'm going to make sure that they're unsigned
even though that's by default. So if I say unsigned int a and assign it to 60,
that's actually going to be represented in binary as 0 0 1 1
and then 11 00.
If I create another unsigned variable and I say int b
and I assign that the value of 13,
that's going to actually be represented as in binary 0 0
00 1 1 0 1. You can do the conversions there.
But what I want to demonstrate here is that when you set these binary numbers up,
you can turn off the bits by using the different bitwise operands.
So now then I'm going to just create a int result,
and I'm going to say that's going to be equal to 0.
E is going to hold the result of the bitwise operation.
operation. Now if I say c equals a and I
apply the bitwise operand and a and b,
now what that should do is if a is equal to 1 and b is equal to 1,
that bits going to be turned on. So what would you expect the result of this v.
Well, you look at the first bit of a and you look at the first bit of b
and they're both 0.
So the result is going to be 0 because
if you do it true in a and a b, they both have to be true in order to be 1.
So the next one is also going to be 0. The next one is 1 and 0, the third bit.
So it's still 0, 1 and 0 is still 0. And then now we have a 1 and a 1.
So now we finally have a true. We have another 1 and 1. We have a true.
And then 0 and 0 is going to be 0 and then a 0 and 1
is going to be 0.
So the result if I were to try to print out c, it's going to print out
the value in decimal format. If I were to do something like that,
it's going to print out the decimal equivalent of that binary number,
which would be the equivalent of 0 0 0 0.
And this is all converting binary to decimal, so you need to understand how to do that
to understand this example. But 0 0 0 0 1 1 0 0
is actually 1 3 7, the value is actually
is 12, 1 3 6 12.
So this would print out twelve
if I were to print out c
or result would be better.
So if I run this, you're going to see that the value is 12.
It actually turned off and on all the bits based on the ampersand comparison.
So now I say run,
we see that the value is in d12
because it's turning off and on the bits
and it's going to actually be represented as 0 0 0
1 1 0 0 which is the value 12 because we're printing out a decimal.
If I were to change this and I want to now do an or
and I'm still doing the or and the or remember is the parallel bar
right next to the enter,
now I'm only going to turn on bits if
either 1 is true. So 00,
both of those are false. Again, I'm comparing up here.
I'm comparing these bits for 16 and 13.
16 is represented as binary 0 0 1 1 1 1 0 0.
13 is represented in binary 0 0 0 0 1 1 0 is 1.
Each one of those numbers represents a bit.
So the first bit in 60 is 0, the first bit in 13 is 0.
And if I order those together, 0 and 0, I'm still going to get 0. So that's the first result of the first bit.
Second bit 00 again. Third bit is 1 for 60
and it's 0 for 13.
Now all that means I have to have 1 true so that's going to be a 1.
Same goes for bit number 4 and 16, 13. So now I have a 1 again.
And then a 1 and 1, they're both true. So again 1,
all I need is 1 true, another 1.
Both false so that's not going to be true. 0, remember is not true, 1 is true
and 0 11. So now I have 0 0 1 1 1 1 0 1.
And the value of that in decimal if I were to print it out is again you
have to understand how to convert binary to decimal but it basically goes 1
3 7 15 30
61. So this is going to print out 61.
End this program and
rebuild it, and we are going to see a value of 61.
So that's bitwise operators. And again, it's a more kind of
it's a more kind of advanced programs, but
it's a nice way to represent a lot of data by using ampersands and so forth,
by turning on and turning off bits, essentially. So you could
play around with this.You could do the exclusive or which is the carrot.
The carrot is above the 6, number 6 on the keyboard.
You would see a different result. If you would add the tilde, that's just going to basically turn everything off.
So for a and a is equal to 60, 0 0 1 1 1 1 0 0,
it's not going to be equal to 1 1 0 0 0 0 1 1.
Another really cool thing you can do with the binary operators is shifting,
shifting left and right. There's a couple key things you know when you
need to shift left or right.
First of all, we know that an unsigned int
means that can only be positive. It can't be negative.
So if you're storing a negative value in there, the compile will convert it will be longer, it'll take up a lot of size.
So remember unsigned ints mean that you can only have positive values.
Signed integers mean that they can be negative or positive.
But if you want to shift, remember
in order to shift to the left, so now if we say
result equals and let's say we want to shift a,
let's say, by 2,
the other important thing you want to know is when you have the integers,
integers are, remember,
they're 4 bytes on most platforms. It depends you can get the
size by doing the size of operator. So the integer is really
4 is 32 bits
so really the number is something like this. The 16
something like that what is that 4 8 12 16 20 24.
So you probably something like that and something like that.
That's really the number. I only showed
the last 8 bits because the rest were 0s. But if you look at this as a 32-bit
integer, which is 4 bytes, this is what it looks like in binary,
4 0s 4 0s 4 0s 4 0s 4 0s 4 0s
and then the 0 0 1 1 1 1 0 0.
And so you got to know the size when you do the shifting left or right because
if you shift more than 2, it's not going to be clear.
It doesn't drop off or anything like that.
So again let me just make sure 48 12 16 20
24 28 32 and the same would go for 13.
So if you were to shift to the left a
greater than greater than 2, what you're end up going to have is these
1s are going to shift to the left too. So the result is going to be
still all those preceding 0s,
but then you're going to have 1 1 1 1 0 0 0 0.
And that is going to be equal to 240.
And if I do a quick conversion I do it in my head by saying 1 3 7
15 30 60 122 40,
but we can confirm that by building and running
and you'll see that the result is 240.
And we see the result is 240.
So now if you want to actually shift to my more than 2 s
say you want to shift by 4, this is when it becomes important to understand that it's a 32-bit number.
So here you would actually have to use some of those 0s.
So if you want to shift by 4 really what you would have is you would just have
something like that.
And then if you want to group them by 4, you'd have
something
like that. So the result here
would be again if I do this in my head, you have 1 3
7 15 30 60 120 240
480 and then 960.
Hopefully, I did that right. Again when we run this
and we say 960,
so that's shifting to the left. If you want to shift to the right,
you use the greater than symbols.
So shifting to the right binary right shift operator,
you do the greater than. Binary left shift operator, you do the less than.
So here if you're going to shift to the right, you want to move to the right 4.
And what happens if you have the end here, so if you have your original 60,
you try to go 4. You're going to have digits that just get dropped off.
So instead of having these
last 4 which originally again we have 60. So we have
0 0 0 1 1 1 1 0 0, we have to move over 4.
So we're going to end up losing 2 bits because they're just going to drop off.
And what we're going to end up with is
something like this
0 0. And so this would just be equal to 3,
something like that so you actually lose bits because you're shifting to the right too much,
you have the result of 3. So you have to be careful when you shift left and the right,
make sure you use those 32 bits
4 bytes again depending on your system.
It's a quick summary of bitwise operators.
When you get more advanced, you have to understand
how you can actually check if a particular bit is 1 or 0.
It's pretty simple. You just do an and on it.
But you do have to write a little bit more code.
This lecture was not intended to be an exhaustive look at bitwise operators.
I wanted to give an overview, give you
a good head start on it. But in order to understand these operators more, you're going to have to study
quite a bit more and use them and practice them.
So I hope this was helpful. Again, it can get a little confusing so you want to follow
and you want to play around with it. But again, what's the best way to learn, write some code,
learn some examples. Thank you.