I'm reading through a book on C++ standards: "Thinking in C++" by Bruce Eckel.
A lot of the C++ features are explained really well in this book but I have come to a brick wall on something and whether it may or may not help me when I wish to program a game for example, it's irking me as to how it works and I really cannot get it from the explanation given.
I was wondering if anybody here could help me in explaining how this example program actually works:
printBinary.h -
void printBinary(const unsigned char val);
printBinary.cpp -
#include <iostream>
void printBinary(const unsigned char val) {
for (int i = 7; i >= 0; i--) {
if (val & ( 1 << i))
std::cout << "1";
else
std::cout << "0";
}
}
Bitwise.cpp -
#include "printBinary.h"
#include <iostream>
using namespace std;
#define PR(STR, EXPR) \
cout << STR; printBinary(EXPR); cout << endl;
int main() {
unsigned int getval;
unsigned char a, b;
cout << "Enter a number between 0 and 255: ";
cin >> getval; a = getval;
PR ("a in binary: ", a);
cin >> getval; b = getval;
PR ("b in binary: ", b);
PR("a | b = ", a | b);
This program is supposed to explain to me how the shift bitwise operator (<<) and (>>) work but I simply don't get it, I mean sure I know how it works using cin and cout but am I stupid for not understanding this?
this piece in particular confuses me more so than the rest:
if (val & ( 1 << i))
Thanks for any help
if (val & ( 1 << i))
Consider the following binary number (128):
10000000
& is bitwise "AND" - 0 & 0 = 0, 0 & 1 = 1 & 0 = 0, 1 & 1 = 1.
<< is bitwise shift operator; it shifts the binary representation of the shifted number to left.
00000001 << 1 = 00000010; 00000001 << 2 = 00000100.
Write it down on a piece of paper in all iterations and see what comes out.
1 << i
takes the int-representation of 1 and shifts it i bits to the left.
val & x
is a bit-wise AND between val and x (where x is 1 << i in this example).
if(x)
tests if x converted to bool is true. Any non-zero value of an integral type converted to bool is true.
<< has two different meanings in the code you shown.
if (val & (1 << i))
<< is used to bitshift, so the value 1 will be shifted left by i bits
cout << ....
The stream class overloads the operator <<, so here it has a different meaning than before.
In this case, << is a function that outputs the contents on its right to cout
if (val & ( 1 << i))
This checks if the bit in i-th position is set. (1 << i) is something like 000001000 for i = 3. Now if the & operation returns non-zero, that means val had the corresponding bit set.
Related
I'm not very familiar with bit operators and I have this use case : when we use the left shift operator << in C++ the number will be shifted and 0 will be placed at the right of number, I want to place 1 and not zero at the right.
I mean if I have a number 00000000 and I make << 3 the result need to be 00000111 and not 0 !
Simple approach is to left shift 1 by the number of bits you want set and then subtract 1
(1 << n) - 1
E.g.
cout << (1 << 2) - 1 << '\n'; // prints 3
cout << (1 << 3) - 1 << '\n'; // prints 7
cout << (1 << 4) - 1 << '\n'; // prints 15
cout << (1 << 5) - 1 << '\n'; // prints 31
But note this only works if n is less than the number of bits in an integer. Otherwise it's undefined behaviour.
Here's a solution that works on any number:
int one_shift(int val, int n) {
return ~(~0 << n) | (val << n);
}
Breakdown:
~0 evaluates to 0xFFFFFFFF e.g. all 1's
~0 << n shifts 0xFFFFFFFF by N places, resulting in a number with N zeroes on the end
~(~0 << n) flips all these bits, resulting in a number with only the last N bits set
| (val << n) then does a regular left shift on our original number by N places, and sets the last N bits by oring it with our other value
Also, here's a version that works on any integer type:
template<typename T>
T one_shift(T val, int n) {
return ~(~static_cast<T>(0) << n) | (val << n);
}
Then that's not what a left shift is.
You will have to set those bits to 1 yourself.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I need some further explanation on a code I don't quite understand.
This is a program that takes a num = 25 and starts moving it left with a << syntax.
#include <iostream>
using namespace std;
int main(){
cout << "Shift to the left" << endl;
short numb = 25;
cout << "Starting value: ";
for (int i = sizeof(short)*8 - 1; i >= 0; i--)
cout << (((1 << i) & numb) == 0 ? "0" : "1");
cout << " " << numb << endl;
for (int i = 0; i < sizeof(short)*8; i++){
numb <<= 1;
cout << "Shift" << (i+1 < 10 ? "0" : "")
<< i+1 << " : ";
for (int i = sizeof(short)*8 - 1; i >= 0; i--)
cout << (((1 << i) & numb) == 0 ? "0" : "1");
cout << " " << numb << endl;
}
return 0;
}
After the line where the first for loop is executed (the count line), what value does the & syntax takes into consideration? ((1 << i) & numb)
I don't understand how the program can take ((1 << i) & numb), compares the two and return a value.
Also why do we declare i to be sizeof(short)*8 - 1? Why don't we just type in 16-1? Is there a specific reason to do this or is it just to make the code look more complex?
And an explanation on why we even declare i to be 15-1 would be highly appreciative.
Hope I haven't given you too much, I'm a beginner and I need some guidance with some problems to which answers I can't still yet come up with by myself.
Thanks!
The bitwise shift operators are the right-shift operator (>>), which moves the bits of shift_expression to the right, and the left-shift operator (<<), which moves the bits of shift_expression to the left. There are also two complex operators that can be used to assign the value directly to the value on left. These are the <<= operator and the >>= operator.
The left-shift operator causes the bits in shift-expression to be shifted to the left by the number of positions specified by additive-expression. The bit positions that have been vacated by the shift operation are zero-filled. A left shift is a logical shift (the bits that are shifted off the end are discarded, including the sign bit).
The right-shift operator causes the bit pattern in shift-expression to be shifted to the right by the number of positions specified by additive-expression. For unsigned numbers, the bit positions that have been vacated by the shift operation are zero-filled. For signed numbers, the sign bit is used to fill the vacated bit positions. In other words, if the number is positive, 0 is used, and if the number is negative, 1 is used.
Demo Code:
using namespace std;
int main() {
int a = 1, b = 3;
// a right now is 00000001
// Left shifting it by 3 will make it 00001000, ie, 8
a = a << 3;
cout << a << endl; // Gives output 8
// Right shifting a by 2 will make it 00000010, ie, 2
a = a >> 2;
cout << a << endl; // Gives output 2
return 0;
}
The result of a right-shift of a signed negative number is implementation-dependent. If you left-shift a signed number so that the sign bit is affected, the result is undefined.
I need to covert hexadecimal string to binary then pass the bits into different variables.
For example, my input is:
std::string hex = "E136";
How do I convert the string into binary output 1110 0001 0011 0110?
After that I need to pass the bit 0 to variable A, bits 1-9 to variable B and bits 10-15 to variable C.
Thanks in advance
How do I convert the string [...]?
Start with result value of null, then for each character (starting at first, indicating most significant one) determine its value (in range of [0:15]), multiply the so far received result by 16 and add the current value to. For your given example, this will result in
(((0 * 16 + v('E')) * 16 + v('1')) * 16 + v('3')) + v('6')
There are standard library functions doing the stuff for you, such as std::strtoul:
char* end;
unsigned long value = strtoul(hex.c_str(), &end, 16);
// ^^ base!
The end pointer useful to check if you have read the entire string:
if(*char == 0)
{
// end of string reached
}
else
{
// some part of the string was left, you might consider this
// as error (could occur if e. g. "f10s12" was passed, then
// end would point to the 's')
}
If you don't care for end checking, you can just pass nullptr instead.
Don't convert back to a string afterwards, you can get the required values by masking (&) and bitshifting (>>), e. g getting bits [1-9]:
uint32_t b = value >> 1 & 0x1ffU;
Working on integrals is much more efficient than working on strings. Only when you want to print out the final result, then convert back to string (if using a std::ostream, operator<< already does the work for you...).
While playing with this sample, I realized that I gave a wrong recommendation:
std::setbase(2) does not work by standard. Ouch! (SO: Why doesn't std::setbase(2) switch to binary output?)
For conversion of numbers to string with binary digits, something else must be used. I made this small sample. Though, the separation of bits is considered as well, my main focus was on output with different bases (and IMHO worth another answer):
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <string>
std::string bits(unsigned value, unsigned w)
{
std::string text;
for (unsigned i = 0; i < w || value; ++i) {
text += '0' + (value & 1); // bit -> character '0' or '1'
value >>= 1; // shift right one bit
}
// text is right to left -> must be reversed
std::reverse(text.begin(), text.end());
// done
return text;
}
void print(const char *name, unsigned value)
{
std::cout
<< name << ": "
// decimal output
<< std::setbase(10) << std::setw(5) << value
<< " = "
// binary output
#if 0 // OLD, WRONG:
// std::setbase(2) is not supported by standard - Ouch!
<< "0b" << std::setw(16) << std::setfill('0') << std::setbase(2) << value
#else // NEW:
<< "0b" << bits(value, 16)
#endif // 0
<< " = "
// hexadecimal output
<< "0x" << std::setw(4) << std::setfill('0') << std::setbase(16) << value
<< '\n';
}
int main()
{
std::string hex = "E136";
unsigned value = strtoul(hex.c_str(), nullptr, 16);
print("hex", value);
// bit 0 -> a
unsigned a = value & 0x0001;
// bit 1 ... 9 -> b
unsigned b = (value & 0x03FE) >> 1;
// bit 10 ... 15 -> c
unsigned c = (value & 0xFC00) >> 10;
// report
print(" a ", a);
print(" b ", b);
print(" c ", c);
// done
return 0;
}
Output:
hex: 57654 = 0b1110000100110110 = 0xe136
a : 00000 = 0b0000000000000000 = 0x0000
b : 00155 = 0b0000000010011011 = 0x009b
c : 00056 = 0b0000000000111000 = 0x0038
Live Demo on coliru
Concerning, the bit operations:
binary bitwise and operator (&) is used to set all unintended bits to 0. The second value can be understood as mask. It would be more obvious if I had used binary numbers but this is not supported in C++. Hex codes do nearly as well as a hex digit represents always the same pattern of 4 bits. (as 16 = 24) After some time of practice, you usually learn to "see" the bits in the hex code.
About the right shift (>>), I was not quite sure. OP didn't require that bits have to be moved somewhere – only that they had to be separated into distinct variables. So, these right-shift's might be obsolete.
So, this question which seemed to be trivial leaded to a surprising enlightment (for me).
What's the meaning of binary(number >> 1), and how does it work in the following code? Could somebody explain it to me in detail? Thank you!
#include <iostream.h>
void binary(int);
int main() {
int number = 3;
cout << number << endl;
binary(number);
}
void binary(int number) {
if(number <= 1) {
cout << number;
return;
}
int remainder = number%2;
binary(number >> 1); //How does this work exactly?
cout << remainder;
}
The << and >> operators are bit-shift operators; they change the value based off of the binary representation of the number; an example will clarify:
001010 (10)
If we do << 1 (left shift 1 bit), then we get:
010100 (20)
If you noticed, the above is equivalent to multiplying by two; in fact, shifting left n bits is equivalent to multiplying by 2 to the nth power!
If we do >> 1 (right shift 1 bit) to the original, we get this:
000101 (5)
Again, if you look carefully, you'll notice the above is equivalent to dividing by 2! In fact, the right shift operator is the inverse operator of the left shift operator, so right shifting n bits is equivalent to dividing by 2 to the nth power!
Also, void main() is just plain wrong, so don't use it. <iostream.h> should be replaced by <iostream> as the former was used prior to standard ISO C++.
Here is a C++ program I see today:
for (int i = 0; i < LEVELS; ++i)
{
int pyr_rows = rows >> i; // what is the usage of >> i here ?
int pyr_cols = cols >> i; // why we what to use it in this way.
depths_curr_[i].create (pyr_rows, pyr_cols);
}
What I am curious about is the usage of operator >> here. I tried a simple program and type the results:
int rows = 5;
int cols = 3;
for (int i=0; i<5; i++)
{
int pyr_rows = rows >> i;
std::cout << "current i is:" << i << std::endl;
std::cout << "pyr_rows is: " << pyr_rows << std::endl << std::endl;
int pyr_cols = cols >> i;
std::cout << "current i is:" << i << std::endl;
std::cout << "pyr_cols is: " << pyr_cols << std::endl << std::endl;
}
And the result is like this:
current i is:0
pyr_rows is: 5
current i is:0
pyr_cols is: 3
current i is:1
pyr_rows is: 2 // from now on
// the outputs of pyr_rows and pyr_cols are weird to me
current i is:1
pyr_cols is: 1
current i is:2
pyr_rows is: 1
current i is:2
pyr_cols is: 0
current i is:3
pyr_rows is: 0
current i is:3
pyr_cols is: 0
current i is:4
pyr_rows is: 0
current i is:4
pyr_cols is: 0
Why the output is like this? Can anyone explain it? And why we want to use this in this way? Any situation we prefer to do it?
It's not the "extraction operator", it's the right-shift operator, which is what >> meant before C++ started inventing crazy ways to overload it. I'm guessing from the pyr that this is pyramidal image processing? The idea is that every time i increases by one, the number of rows and columns in the pyramid are halved. That's because a right shift by i is basically a division (rounding down) by 2^i.
In the case you've outlined, >> stands for the right shift operator. If you consider an integer written in binary form:
01101 = 13
The >> i operator will make the bits above be shifted towards the right i times. So when i = 2, the above would result in:
00011 = 3
This is useful to efficiently divide integers by powers of 2. The result ends up rounded down, so 3 >> 1 equals 1, but -3 >> 1 equals -2.
This is the arithmetic shift, which means the leading bit gets padded, so that negative numbers can remain negative after the shift (leading bit 1). Some languages also have the >>> operator for the logical shift, which always pads the leading bits with zeroes.
It is not an "extraction operator", it is the original bitwise shift (right) operator, that was in C before anyone had even considered making a C++ language. It is now being used as an operator for files to input and output.
int x = 4;
int y = 1;
cout << (x >> y) << endl;
will produce 4 shifted right 1 bit, which should show the value 2.