I was expecting:
int main( int argc, char *argv[] ) { unsigned char m = 32; register unsigned mask = (1<<m); std::cout << std::hex << mask << '\n'; return 0; }
to print 0 but instead this program compiled with g++ (and VC++.NET2003 too) prints 1!
If I change (1<<m) by (1<<32) or if change the program for:
int main( int argc, char *argv[] ) { unsigned char m = 31; register unsigned mask = (1<<m)<<1; std::cout << std::hex << mask << '\n'; return 0; }
it gives me the expected 0.
In the C++ standard document, section 5.8. It is written
"The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand."
The root for this behavior probably originates from C and the safe way to perform a bit shift when the number of bits to shift may exceed the length of the left operand is to implement the shift operation in a function:
Example, almost but not universally portable:
#include <climits> unsigned int safe_uint_shift(unsigned int value, unsigned int bits) { if( bits > (CHAR_BIT*std::sizeof(unsigned int) ) { return 0; } else { return value << bits; } }
Put it in a header and make it inline if you like.
This solution has been proposed by Jack Klein.
The other way that I have used is to promote the left operand to an integer type having enough bits:
register unsigned mask = (static_cast<unsigned long long>(1)<<m)<<1;
Suppose we have
class A { private: class B { }; };
and we would like to define operator<< for class B. I had this situation yesterday and it took me few tries to make it work. I first tried:
class A { ... }; std::ostream operator<<( ostream &, const A::B & );
It did not work because the compiler complained that B was private. My second attempt:
class A { private: class B { }; static std::ostream &operator<<( ostream &, const B & ); };
I was getting closer to the solution but this was still not quite right. Apparently, you do not have the right to declare operator<< as a static member of another class or as soon as an operator is defined as a class member, automatically, the compiler expect the left operand to be of this class type.
Then I tried this:
class A { private: class B { }; friend std::ostream &operator<<( ostream &, const B & ); }; std::ostream &operator<<( ostream &o, const A::B &b ) { }
This time, I am not sure why but the linker now was complaining about duplicate symbols for my operator<< function. Not sure if it is the code that has a problem. It looks good to me. I suspect that maybe it is parameter type mangling problem and the compiler does not recognize 'const B &' as the same as 'const A::B &' but anyhow, I did not pursue the investigation I have finally made the code work like this:
class A { private: class B { }; friend std::ostream &operator<<( ostream &o, const B &b ) { } };
I want you to find in this blog informations about C++ programming that I had a hard time to find in the first place on the web.
Sun | Mon | Tue | Wed | Thu | Fri | Sat |
---|---|---|---|---|---|---|
<< < | Current | > >> | ||||
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |