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;








1
















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.










share|improve this 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 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

















1
















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.










share|improve this 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 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













1












1








1


1







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.










share|improve this question















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++






share|improve this question













share|improve this question











share|improve this question




share|improve this question










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 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

















  • 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
















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












1 Answer
1






active

oldest

votes


















2














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.)






share|improve this answer



























  • 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















1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














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.)






share|improve this answer



























  • 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
















2














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.)






share|improve this answer



























  • 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














2












2








2







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.)






share|improve this answer















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.)







share|improve this answer














share|improve this answer



share|improve this answer








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


















  • 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









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.





Popular posts from this blog

Kamusi Yaliyomo Aina za kamusi | Muundo wa kamusi | Faida za kamusi | Dhima ya picha katika kamusi | Marejeo | Tazama pia | Viungo vya nje | UrambazajiKuhusu kamusiGo-SwahiliWiki-KamusiKamusi ya Kiswahili na Kiingerezakuihariri na kuongeza habari

Swift 4 - func physicsWorld not invoked on collision? The Next CEO of Stack OverflowHow to call Objective-C code from Swift#ifdef replacement in the Swift language@selector() in Swift?#pragma mark in Swift?Swift for loop: for index, element in array?dispatch_after - GCD in Swift?Swift Beta performance: sorting arraysSplit a String into an array in Swift?The use of Swift 3 @objc inference in Swift 4 mode is deprecated?How to optimize UITableViewCell, because my UITableView lags

Access current req object everywhere in Node.js ExpressWhy are global variables considered bad practice? (node.js)Using req & res across functionsHow do I get the path to the current script with Node.js?What is Node.js' Connect, Express and “middleware”?Node.js w/ express error handling in callbackHow to access the GET parameters after “?” in Express?Modify Node.js req object parametersAccess “app” variable inside of ExpressJS/ConnectJS middleware?Node.js Express app - request objectAngular Http Module considered middleware?Session variables in ExpressJSAdd properties to the req object in expressjs with Typescript