Why doesn't left bit shift shift beyond 31 for long int datatype?
Although your x
is of type long int
, the 1
is not. 1
is an int
, so 1<<63
is indeed undefined.
Try (static_cast<long int>(1) << 63)
, or 1L << 63
as suggested by Wojtek.
bit shifting with unsigned long type produces wrong results
1 << 63
will be computed in int
arithmetic, and your int
is probably 32 bit.
Remedy this by promoting the left argument: 1ULL << 63
will do it.
ULL
means the expression will be at least 64 bits.
Why do 1ll i does give us correct answer but not long long i ; 1 i?
C++11 (N3690) 5.8 Shift operators [expr.shift] p1:
The operands shall be of integral or unscoped enumeration type and integral promotions are performed.
The type of the result is that of the promoted left operand.
So the type of 1 << i
is int
, whereas 1LL << i
has type long long
, which can usually represent a greater range of values.
The shift operators are exceptional here; most other operators follow the usual arithmetic conversions [5 p10], which cause both operands to be converted to the same type, roughly speaking the larger of the two.
Why doesn't left bit-shift, , for 32-bit integers work as expected when used more than 32 times?
This is caused due to a combination of an undefined behaviour in C and the fact that code generated for IA-32 processors has a 5 bit mask applied on the shift count. This means that on IA-32 processors, the range of a shift count is 0-31 only. 1
From The C programming language 2
The result is undefined if the right operand is negative, or greater than or equal to the number of bits in the left expression’s type.
From IA-32 Intel Architecture Software Developer’s Manual 3
The 8086 does not mask the shift count. However, all other IA-32 processors (starting with the Intel 286 processor) do mask the shift count to 5 bits, resulting in a maximum count of 31. This masking is done in all operating modes (including the virtual-8086 mode) to reduce the maximum execution time of the instructions.
1 http://codeyarns.com/2004/12/20/c-shift-operator-mayhem/
2 A7.8 Shift Operators, Appendix A. Reference Manual, The C Programming Language
3 SAL/SAR/SHL/SHR – Shift, Chapter 4. Instruction Set Reference, IA-32 Intel Architecture Software Developer’s Manual
C left shift on 64 bits fail
Because 1
is an int
, 32 bits, so (1 << 27)*27
overflows. Use 1ull
.
Regarding your comment, if x
is a uint64_t
, then 1 << x
is still an int
, but for the multiplication it would be cast to uint64_t
, so there'd be no overflow. However, if x >= 31
, 1 << x
would be undefined behaviour (as the resulting value cannot be represented by a signed 32 bit integer type).
Bitwise operation for unsigned long long int is not applied when it's over 32bits
Your temp
variable only has 32 bits as it is an unsigned int
. Change its type to unsigned long long
to solve your problem.
What happens?
In this line:
plain |= (temp << (5 * i));
The variable temp
has unsigned int
type which is typically a 32 bit type. The left shift is therefore also a 32 bit shift and whatever is shifted beyond 32 bits is discarded. The code also exhibits undefined behaviour when i
is greater than 6 as shifting a value by more bits than its type has is undefined.
There are two ways to solve this. One is to give temp
the right type, the other is to use an appropriate cast to make sure that the shift is an unsigned long long
shift:
plain |= ((unsigned long long)temp << (5 * i));
Why bitwise operator produce error in calculating the maximum range possible using same number of bits as provided in an integer
In 1 << count
the constant 1
is an int
not a long long
.
Then the shift overflows.
You should use 1ll << count
.
How to shift = 32 bits in uint64_t?
How to shift >= 32 bits in
uint64_t
?
If your compiler supports long long
:
boost::uint64_t x = 1LL << 32;
Otherwise:
boost::uint64_t x = boost::uint64_t(1) << 32;
Shouldn't it be fine since the type has 64 bits?
No. Even though x
is 64 bits, 1
isn't. 1
is 32 bits. How you use a result has no effect on how that result is generated.
Related Topics
How to Make a Multiple-Read/Single-Write Lock from More Basic Synchronization Primitives
When Do I Really Need to Use Atomic<Bool> Instead of Bool
Should I Pass an Std::Function by Const-Reference
How Is the C++ Exception Handling Runtime Implemented
Why Does the Enhanced Gcc 6 Optimizer Break Practical C++ Code
C++ Reading the Data Part of a Wav File
Is #Pragma Once Part of the C++11 Standard
Common Reasons for Bugs in Release Version Not Present in Debug Mode
How to Use Formatmessage() Properly in C++
Programmatically Reading a Web Page
Concat Two 'Const Char' String Literals
Blur Effect Over a Qwidget in Qt
<Iostream> VS. <Iostream.H> VS. "Iostream.H"
Vector That Can Have 3 Different Data Types C++
Sfinae Works Differently in Cases of Type and Non-Type Template Parameters