Why Are Bitwise Shifts (<< and >>) Used for Cout and Cin

When using cout and cin, what are the and operators doing and why do we use them?

They are called the stream insertion operator (<<) and the stream extraction operator (>>).

These are the same operators as the left and right bit shift operators (even though they have different names). The bit shift operators are overloaded, so that when the left side is a stream, they read from or write to that stream.

They're just like any function call - it works like:

leftShift(leftShift(leftShift(leftShift(cout, "You are "), age), " years old!"), endl);

except that the function is called operator<< instead of leftShift.

Strictly speaking, there's no reason that a function called leftShift has to do a left shift, and likewise there's no reason a function called operator<< has to do a left shift.

How do I use bitwise shifts with cout?

Just use parentheses:

#include <iostream>

int main()
{
std::cout << (1 << 5) << std::endl;
}

std::cout << 1 << 5 means "push to output stream first integer literal 1, followed by integer 5". However, adding parantheses changes the order of evaluation, and 1 << 5 is evaluated first, resulting in std::cout << 32 << std::endl; expression.

Should operator be implemented as a friend or as a member function?

The problem here is in your interpretation of the article you link.

Equality

This article is about somebody that is having problems correctly defining the bool relationship operators.

The operator:

  • Equality == and !=
  • Relationship < > <= >=

These operators should return a bool as they are comparing two objects of the same type. It is usually easiest to define these operators as part of the class. This is because a class is automatically a friend of itself so objects of type Paragraph can examine each other (even each others private members).

There is an argument for making these free standing functions as this lets auto conversion convert both sides if they are not the same type, while member functions only allow the rhs to be auto converted. I find this a paper man argument as you don't really want auto conversion happening in the first place (usually). But if this is something you want (I don't recommend it) then making the comparators free standing can be advantageous.

Streaming

The stream operators:

  • operator << output
  • operator >> input

When you use these as stream operators (rather than binary shift) the first parameter is a stream. Since you do not have access to the stream object (its not yours to modify) these can not be member operators they have to be external to the class. Thus they must either be friends of the class or have access to a public method that will do the streaming for you.

It is also traditional for these objects to return a reference to a stream object so you can chain stream operations together.

#include <iostream>

class Paragraph
{
public:
explicit Paragraph(std::string const& init)
:m_para(init)
{}

std::string const& to_str() const
{
return m_para;
}

bool operator==(Paragraph const& rhs) const
{
return m_para == rhs.m_para;
}
bool operator!=(Paragraph const& rhs) const
{
// Define != operator in terms of the == operator
return !(this->operator==(rhs));
}
bool operator<(Paragraph const& rhs) const
{
return m_para < rhs.m_para;
}
private:
friend std::ostream & operator<<(std::ostream &os, const Paragraph& p);
std::string m_para;
};

std::ostream & operator<<(std::ostream &os, const Paragraph& p)
{
return os << p.to_str();
}

int main()
{
Paragraph p("Plop");
Paragraph q(p);

std::cout << p << std::endl << (p == q) << std::endl;
}

What does the statement if (counter & (1j)) mean and how does it work?

The statement:

if (counter & (1<<j))

checks if the j-th bit of counter is set. In more detail, 1 << j uses shifting of 1 to generate a bit mask in which only the j-th bit is set. The & operator then masks out the j-bit of counter; if the result is not zero (which means that the j-th bit of counter was set), the condition is satisfied.

Consider the following example. If counter is 320, its binary representation is 101000000, which means that the 6th bit (the one corresponding to the value of 64) is set; let's test for that bit. The bit mask is generated by shifting 1, which has the binary representation 000000001, 6 places to the right, which results in the binary value 001000000. The value of counter, namely:

101000000

is combined with &, which is the bitwise and-operator, with the bit mask as follows:

  101000000
& 001000000
---------
001000000

The value 001000000 again corresponds to the value of 64; however this is not important here, it only matters that it is not zero (as it has a nonzero bit, namely the bit for which we intended to check). In total, the condition

if ( 64 )

is satisfied. In the semantics of C (which does not feature a native Boolean data type) any nonzero value is treated as true when checked with if.

C++: what does (ab) mean?

1 << 1 means:

00000000 00000001 changes to 00000000 00000010

1 << 8 means:

00000000 00000001 changes to 00000001 00000000

It's a bit shift operation. For every 1 on the right, you can think of yourself as multiplying the value on the left by 2. So, 2 << 1 = 4 and 2 << 2 = 8. This is much more efficient than doing 1 * 2.

Also, you can do 4 >> 1 = 2 (and 5 >> 1 = 2 since you round down) as the inverse operation.

What is (x & 1) and (x = 1)?

These are Bitwise Operators (reference).

x & 1 produces a value that is either 1 or 0, depending on the least significant bit of x: if the last bit is 1, the result of x & 1 is 1; otherwise, it is 0. This is a bitwise AND operation.

x >>= 1 means "set x to itself shifted by one bit to the right". The expression evaluates to the new value of x after the shift.

Note: The value of the most significant bit after the shift is zero for values of unsigned type. For values of signed type the most significant bit is copied from the sign bit of the value prior to shifting as part of sign extension, so the loop will never finish if x is a signed type, and the initial value is negative.

How to perform multiplication, using bitwise operators?

To multiply by any value of 2 to the power of N (i.e. 2^N) shift the bits N times to the left.

0000 0001 = 1 

times 4 = (2^2 => N = 2) = 2 bit shift : 0000 0100 = 4

times 8 = (2^3 -> N = 3) = 3 bit shift : 0010 0000 = 32

etc..

To divide shift the bits to the right.

The bits are whole 1 or 0 - you can't shift by a part of a bit thus if the number you're multiplying by is does not factor a whole value of N
ie.

since: 17 = 16  + 1 
thus: 17 = 2^4 + 1

therefore: x * 17 = (x * 16) + x in other words 17 x's

thus to multiply by 17 you have to do a 4 bit shift to the left, and then add the original number again:

==> x * 17 = (x * 16) + x 
==> x * 17 = (x * 2^4) + x
==> x * 17 = (x shifted to left by 4 bits) + x

so let x = 3 = 0000 0011

times 16 = (2^4 => N = 4) = 4 bit shift : 0011 0000 = 48

plus the x (0000 0011)

ie.

    0011 0000  (48)  
+ 0000 0011 (3)
=============
0011 0011 (51)

Edit: Update to the original answer. Charles Petzold has written a fantastic book 'Code' that will explain all of this and more in the easiest of ways. I thoroughly recommend this.



Related Topics



Leave a reply



Submit