Weird result in left shift (1ull << s == 1 if s == 64) [duplicate]Why doesn't left bit-shift, “<<”, for 32-bit integers work as expected when used more than 32 times?problem with socket programming in cc++Why can't I forward-declare a class in a namespace using double colons?C++11 introduced a standardized memory model. What does it mean? And how is it going to affect C++ programming?Different floating point result with optimization enabled - compiler bug?Copy a file in a sane, safe and efficient wayWhy does GCC generate 15-20% faster code if I optimize for size instead of speed?Replacing a 32-bit loop counter with 64-bit introduces crazy performance deviationsDifferent cast operator called by different compilersHow does `void_t` workcalculate average runtime with pthread with weird results
Why aren't rainbows blurred-out into nothing after they are produced?
What is the proper name for a circle with a line through it?
List, map function based on a condition
Why do my bicycle brakes get worse and feel more 'squishy" over time?
Suspension compromise for urban use
What is the hottest thing in the universe?
Why does this Jet Provost strikemaster have a textured leading edge?
The more + the + comparative degree
How much can I judge a company based on a phone screening?
How do I ask for 2-3 days per week remote work in a job interview?
Does an Irish VISA WARNING count as "refused entry at the border of any country other than the UK?"
Why does Japan use the same type of AC power outlet as the US?
Doesn't the speed of light limit imply the same electron can be annihilated twice?
What is a "soap"?
Weird resistor with dots around it
How to prevent criminal gangs from making/buying guns?
Align rightarrow in table
Is there a fallacy about "appeal to 'big words'"?
Did Michelle Obama have a staff of 23; and Melania have a staff of 4?
Output the list of musical notes
Are there any cons in using rounded corners for bar graphs?
Do I need to start off my book by describing the character's "normal world"?
What's the relationship betweeen MS-DOS and XENIX?
How can I communicate my issues with a potential date's pushy behavior?
Weird result in left shift (1ull
Why doesn't left bit-shift, “<<”, for 32-bit integers work as expected when used more than 32 times?problem with socket programming in cc++Why can't I forward-declare a class in a namespace using double colons?C++11 introduced a standardized memory model. What does it mean? And how is it going to affect C++ programming?Different floating point result with optimization enabled - compiler bug?Copy a file in a sane, safe and efficient wayWhy does GCC generate 15-20% faster code if I optimize for size instead of speed?Replacing a 32-bit loop counter with 64-bit introduces crazy performance deviationsDifferent cast operator called by different compilersHow does `void_t` workcalculate average runtime with pthread with weird results
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
This question already has an answer here:
Why doesn't left bit-shift, “<<”, for 32-bit integers work as expected when used more than 32 times?
9 answers
Why is the result of
uint32_t s = 64;
uint64_t val = 1ull << s;
and
uint64_t s = 64;
uint64_t val = 1ull << s;
1?
But
uint64_t val = 1ull << 0x40;
gets optimized to 0?
I really don't understand why it equals 1. It does no matter whether I use my VC++ or g++ compiler.
And how can I ensure that 1ull << s
equals 0 when s
equals 64, what's in my opinion is the correct result? I also need the imo. correct result in my program.
c++
marked as duplicate by Kamil Cuk, rustyx, Community♦ Mar 27 at 11:49
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
add a comment |
This question already has an answer here:
Why doesn't left bit-shift, “<<”, for 32-bit integers work as expected when used more than 32 times?
9 answers
Why is the result of
uint32_t s = 64;
uint64_t val = 1ull << s;
and
uint64_t s = 64;
uint64_t val = 1ull << s;
1?
But
uint64_t val = 1ull << 0x40;
gets optimized to 0?
I really don't understand why it equals 1. It does no matter whether I use my VC++ or g++ compiler.
And how can I ensure that 1ull << s
equals 0 when s
equals 64, what's in my opinion is the correct result? I also need the imo. correct result in my program.
c++
marked as duplicate by Kamil Cuk, rustyx, Community♦ Mar 27 at 11:49
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
Which version of Visual C++ are you using? I get 0 in all the cases with VC++ 2017. Compiling inx64 Release
mode.
– sgarizvi
Mar 27 at 11:47
@sgarizvi, I think your compiler is optimizing the shift away. If you check the same thing in Debug, I think you'll be able to reproduce OP's results.
– yzt
Mar 27 at 11:50
@yzt... Indeed, you are right.
– sgarizvi
Mar 27 at 11:51
add a comment |
This question already has an answer here:
Why doesn't left bit-shift, “<<”, for 32-bit integers work as expected when used more than 32 times?
9 answers
Why is the result of
uint32_t s = 64;
uint64_t val = 1ull << s;
and
uint64_t s = 64;
uint64_t val = 1ull << s;
1?
But
uint64_t val = 1ull << 0x40;
gets optimized to 0?
I really don't understand why it equals 1. It does no matter whether I use my VC++ or g++ compiler.
And how can I ensure that 1ull << s
equals 0 when s
equals 64, what's in my opinion is the correct result? I also need the imo. correct result in my program.
c++
This question already has an answer here:
Why doesn't left bit-shift, “<<”, for 32-bit integers work as expected when used more than 32 times?
9 answers
Why is the result of
uint32_t s = 64;
uint64_t val = 1ull << s;
and
uint64_t s = 64;
uint64_t val = 1ull << s;
1?
But
uint64_t val = 1ull << 0x40;
gets optimized to 0?
I really don't understand why it equals 1. It does no matter whether I use my VC++ or g++ compiler.
And how can I ensure that 1ull << s
equals 0 when s
equals 64, what's in my opinion is the correct result? I also need the imo. correct result in my program.
This question already has an answer here:
Why doesn't left bit-shift, “<<”, for 32-bit integers work as expected when used more than 32 times?
9 answers
c++
c++
asked Mar 27 at 11:37
JulianHJulianH
3892 silver badges12 bronze badges
3892 silver badges12 bronze badges
marked as duplicate by Kamil Cuk, rustyx, Community♦ Mar 27 at 11:49
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
marked as duplicate by Kamil Cuk, rustyx, Community♦ Mar 27 at 11:49
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
marked as duplicate by Kamil Cuk, rustyx, Community♦ Mar 27 at 11:49
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
Which version of Visual C++ are you using? I get 0 in all the cases with VC++ 2017. Compiling inx64 Release
mode.
– sgarizvi
Mar 27 at 11:47
@sgarizvi, I think your compiler is optimizing the shift away. If you check the same thing in Debug, I think you'll be able to reproduce OP's results.
– yzt
Mar 27 at 11:50
@yzt... Indeed, you are right.
– sgarizvi
Mar 27 at 11:51
add a comment |
Which version of Visual C++ are you using? I get 0 in all the cases with VC++ 2017. Compiling inx64 Release
mode.
– sgarizvi
Mar 27 at 11:47
@sgarizvi, I think your compiler is optimizing the shift away. If you check the same thing in Debug, I think you'll be able to reproduce OP's results.
– yzt
Mar 27 at 11:50
@yzt... Indeed, you are right.
– sgarizvi
Mar 27 at 11:51
Which version of Visual C++ are you using? I get 0 in all the cases with VC++ 2017. Compiling in
x64 Release
mode.– sgarizvi
Mar 27 at 11:47
Which version of Visual C++ are you using? I get 0 in all the cases with VC++ 2017. Compiling in
x64 Release
mode.– sgarizvi
Mar 27 at 11:47
@sgarizvi, I think your compiler is optimizing the shift away. If you check the same thing in Debug, I think you'll be able to reproduce OP's results.
– yzt
Mar 27 at 11:50
@sgarizvi, I think your compiler is optimizing the shift away. If you check the same thing in Debug, I think you'll be able to reproduce OP's results.
– yzt
Mar 27 at 11:50
@yzt... Indeed, you are right.
– sgarizvi
Mar 27 at 11:51
@yzt... Indeed, you are right.
– sgarizvi
Mar 27 at 11:51
add a comment |
1 Answer
1
active
oldest
votes
This is because on x64, the instruction SHL
(when operating on a 64-bit source/destination operand) only uses the bottom 6 bits of the shift amount. In effect, you are shifting by 0 bits.
From the "Intel 64 and IA-32 Architecture Software Developer's Manual" (can be downloaded from Intel in PDF form, which is hard to link into,) under the entry for "SAL/SAR/SHL/SHR - Shift" instructions:
The count is masked to 5 bits (or 6 bits if in 64-bit mode and REX.W is used). The count range is limited to 0 to 31 (or 63 if 64-bit mode and REX.W is used).
As commented below, it is also an "Undefined Behavior" in the C++ language to shift an integer by more bits than its size. (Thanks to @sgarizvi for the reference.) The C++ standard, under Section 8.5.7 (Shift Operators) states that:
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...
That's why the compiler is producing code that gives different results under different conditions (constant or variable shift count, optimized or not, etc.)
About how to "fix" it, I have no clever tricks. You can do something like this:
template <typename IntT>
IntT ShiftLeft (IntT x, unsigned count)
// Optional check; depends on how much you want to embrace C++!
static_assert(std::is_integral_v<IntT>, "This shift only works for integral types.");
if (count < sizeof(IntT) * 8)
return x << count;
else
return 0;
This code would work for signed and unsigned integer types (left-shift is the same for signed and unsigned values.)
More generally: This is because the behaviour of shifting by the width of the integer (or more) is undefined in C++.
– eerorika
Mar 27 at 11:51
Yes makes sense, thank you for that.
– JulianH
Mar 27 at 12:01
@yzt.. In the C++ Standard draft document, it is mentioned under Section 8.5.7 (Shift Operators) that .....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
– sgarizvi
Mar 27 at 12:17
@sgarizvi Also thanks @yzt I'm only considering s <= 64, I don't have to care about s > 64, so I'm able to stay with the solution:1ull << (s - 1) << 1
.
– JulianH
Mar 27 at 12:31
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
This is because on x64, the instruction SHL
(when operating on a 64-bit source/destination operand) only uses the bottom 6 bits of the shift amount. In effect, you are shifting by 0 bits.
From the "Intel 64 and IA-32 Architecture Software Developer's Manual" (can be downloaded from Intel in PDF form, which is hard to link into,) under the entry for "SAL/SAR/SHL/SHR - Shift" instructions:
The count is masked to 5 bits (or 6 bits if in 64-bit mode and REX.W is used). The count range is limited to 0 to 31 (or 63 if 64-bit mode and REX.W is used).
As commented below, it is also an "Undefined Behavior" in the C++ language to shift an integer by more bits than its size. (Thanks to @sgarizvi for the reference.) The C++ standard, under Section 8.5.7 (Shift Operators) states that:
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...
That's why the compiler is producing code that gives different results under different conditions (constant or variable shift count, optimized or not, etc.)
About how to "fix" it, I have no clever tricks. You can do something like this:
template <typename IntT>
IntT ShiftLeft (IntT x, unsigned count)
// Optional check; depends on how much you want to embrace C++!
static_assert(std::is_integral_v<IntT>, "This shift only works for integral types.");
if (count < sizeof(IntT) * 8)
return x << count;
else
return 0;
This code would work for signed and unsigned integer types (left-shift is the same for signed and unsigned values.)
More generally: This is because the behaviour of shifting by the width of the integer (or more) is undefined in C++.
– eerorika
Mar 27 at 11:51
Yes makes sense, thank you for that.
– JulianH
Mar 27 at 12:01
@yzt.. In the C++ Standard draft document, it is mentioned under Section 8.5.7 (Shift Operators) that .....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
– sgarizvi
Mar 27 at 12:17
@sgarizvi Also thanks @yzt I'm only considering s <= 64, I don't have to care about s > 64, so I'm able to stay with the solution:1ull << (s - 1) << 1
.
– JulianH
Mar 27 at 12:31
add a comment |
This is because on x64, the instruction SHL
(when operating on a 64-bit source/destination operand) only uses the bottom 6 bits of the shift amount. In effect, you are shifting by 0 bits.
From the "Intel 64 and IA-32 Architecture Software Developer's Manual" (can be downloaded from Intel in PDF form, which is hard to link into,) under the entry for "SAL/SAR/SHL/SHR - Shift" instructions:
The count is masked to 5 bits (or 6 bits if in 64-bit mode and REX.W is used). The count range is limited to 0 to 31 (or 63 if 64-bit mode and REX.W is used).
As commented below, it is also an "Undefined Behavior" in the C++ language to shift an integer by more bits than its size. (Thanks to @sgarizvi for the reference.) The C++ standard, under Section 8.5.7 (Shift Operators) states that:
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...
That's why the compiler is producing code that gives different results under different conditions (constant or variable shift count, optimized or not, etc.)
About how to "fix" it, I have no clever tricks. You can do something like this:
template <typename IntT>
IntT ShiftLeft (IntT x, unsigned count)
// Optional check; depends on how much you want to embrace C++!
static_assert(std::is_integral_v<IntT>, "This shift only works for integral types.");
if (count < sizeof(IntT) * 8)
return x << count;
else
return 0;
This code would work for signed and unsigned integer types (left-shift is the same for signed and unsigned values.)
More generally: This is because the behaviour of shifting by the width of the integer (or more) is undefined in C++.
– eerorika
Mar 27 at 11:51
Yes makes sense, thank you for that.
– JulianH
Mar 27 at 12:01
@yzt.. In the C++ Standard draft document, it is mentioned under Section 8.5.7 (Shift Operators) that .....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
– sgarizvi
Mar 27 at 12:17
@sgarizvi Also thanks @yzt I'm only considering s <= 64, I don't have to care about s > 64, so I'm able to stay with the solution:1ull << (s - 1) << 1
.
– JulianH
Mar 27 at 12:31
add a comment |
This is because on x64, the instruction SHL
(when operating on a 64-bit source/destination operand) only uses the bottom 6 bits of the shift amount. In effect, you are shifting by 0 bits.
From the "Intel 64 and IA-32 Architecture Software Developer's Manual" (can be downloaded from Intel in PDF form, which is hard to link into,) under the entry for "SAL/SAR/SHL/SHR - Shift" instructions:
The count is masked to 5 bits (or 6 bits if in 64-bit mode and REX.W is used). The count range is limited to 0 to 31 (or 63 if 64-bit mode and REX.W is used).
As commented below, it is also an "Undefined Behavior" in the C++ language to shift an integer by more bits than its size. (Thanks to @sgarizvi for the reference.) The C++ standard, under Section 8.5.7 (Shift Operators) states that:
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...
That's why the compiler is producing code that gives different results under different conditions (constant or variable shift count, optimized or not, etc.)
About how to "fix" it, I have no clever tricks. You can do something like this:
template <typename IntT>
IntT ShiftLeft (IntT x, unsigned count)
// Optional check; depends on how much you want to embrace C++!
static_assert(std::is_integral_v<IntT>, "This shift only works for integral types.");
if (count < sizeof(IntT) * 8)
return x << count;
else
return 0;
This code would work for signed and unsigned integer types (left-shift is the same for signed and unsigned values.)
This is because on x64, the instruction SHL
(when operating on a 64-bit source/destination operand) only uses the bottom 6 bits of the shift amount. In effect, you are shifting by 0 bits.
From the "Intel 64 and IA-32 Architecture Software Developer's Manual" (can be downloaded from Intel in PDF form, which is hard to link into,) under the entry for "SAL/SAR/SHL/SHR - Shift" instructions:
The count is masked to 5 bits (or 6 bits if in 64-bit mode and REX.W is used). The count range is limited to 0 to 31 (or 63 if 64-bit mode and REX.W is used).
As commented below, it is also an "Undefined Behavior" in the C++ language to shift an integer by more bits than its size. (Thanks to @sgarizvi for the reference.) The C++ standard, under Section 8.5.7 (Shift Operators) states that:
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...
That's why the compiler is producing code that gives different results under different conditions (constant or variable shift count, optimized or not, etc.)
About how to "fix" it, I have no clever tricks. You can do something like this:
template <typename IntT>
IntT ShiftLeft (IntT x, unsigned count)
// Optional check; depends on how much you want to embrace C++!
static_assert(std::is_integral_v<IntT>, "This shift only works for integral types.");
if (count < sizeof(IntT) * 8)
return x << count;
else
return 0;
This code would work for signed and unsigned integer types (left-shift is the same for signed and unsigned values.)
edited Mar 27 at 12:36
answered Mar 27 at 11:48
yztyzt
6,6311 gold badge28 silver badges37 bronze badges
6,6311 gold badge28 silver badges37 bronze badges
More generally: This is because the behaviour of shifting by the width of the integer (or more) is undefined in C++.
– eerorika
Mar 27 at 11:51
Yes makes sense, thank you for that.
– JulianH
Mar 27 at 12:01
@yzt.. In the C++ Standard draft document, it is mentioned under Section 8.5.7 (Shift Operators) that .....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
– sgarizvi
Mar 27 at 12:17
@sgarizvi Also thanks @yzt I'm only considering s <= 64, I don't have to care about s > 64, so I'm able to stay with the solution:1ull << (s - 1) << 1
.
– JulianH
Mar 27 at 12:31
add a comment |
More generally: This is because the behaviour of shifting by the width of the integer (or more) is undefined in C++.
– eerorika
Mar 27 at 11:51
Yes makes sense, thank you for that.
– JulianH
Mar 27 at 12:01
@yzt.. In the C++ Standard draft document, it is mentioned under Section 8.5.7 (Shift Operators) that .....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
– sgarizvi
Mar 27 at 12:17
@sgarizvi Also thanks @yzt I'm only considering s <= 64, I don't have to care about s > 64, so I'm able to stay with the solution:1ull << (s - 1) << 1
.
– JulianH
Mar 27 at 12:31
More generally: This is because the behaviour of shifting by the width of the integer (or more) is undefined in C++.
– eerorika
Mar 27 at 11:51
More generally: This is because the behaviour of shifting by the width of the integer (or more) is undefined in C++.
– eerorika
Mar 27 at 11:51
Yes makes sense, thank you for that.
– JulianH
Mar 27 at 12:01
Yes makes sense, thank you for that.
– JulianH
Mar 27 at 12:01
@yzt.. In the C++ Standard draft document, it is mentioned under Section 8.5.7 (Shift Operators) that .....
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
– sgarizvi
Mar 27 at 12:17
@yzt.. In the C++ Standard draft document, it is mentioned under Section 8.5.7 (Shift Operators) that .....
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
– sgarizvi
Mar 27 at 12:17
@sgarizvi Also thanks @yzt I'm only considering s <= 64, I don't have to care about s > 64, so I'm able to stay with the solution:
1ull << (s - 1) << 1
.– JulianH
Mar 27 at 12:31
@sgarizvi Also thanks @yzt I'm only considering s <= 64, I don't have to care about s > 64, so I'm able to stay with the solution:
1ull << (s - 1) << 1
.– JulianH
Mar 27 at 12:31
add a comment |
Got a question that you can’t ask on public Stack Overflow? Learn more about sharing private information with Stack Overflow for Teams.
Got a question that you can’t ask on public Stack Overflow? Learn more about sharing private information with Stack Overflow for Teams.
Which version of Visual C++ are you using? I get 0 in all the cases with VC++ 2017. Compiling in
x64 Release
mode.– sgarizvi
Mar 27 at 11:47
@sgarizvi, I think your compiler is optimizing the shift away. If you check the same thing in Debug, I think you'll be able to reproduce OP's results.
– yzt
Mar 27 at 11:50
@yzt... Indeed, you are right.
– sgarizvi
Mar 27 at 11:51