Undefined behavior of right-shift in C++

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
7
down vote

favorite
1












From cppreference.com:




For unsigned a and for signed a with nonnegative values, the value of
a >> b is the integer part of a/2b . For negative a, the value of a >>
b is implementation-defined (in most implementations, this performs
arithmetic right shift, so that the result remains negative).



In any case, if the value of the right operand is negative or is
greater or equal to the number of bits in the promoted left operand,
the behavior is undefined.




Why do we have an undefined behavior in case the right operand is greater or equal to the number of bits in the promoted left operand?

It seems to me that the result should be 0 (at least for unsigned/positive integers)...



In particular, with g++ (version 4.8.4, Ubuntu):



unsigned int x = 1;
cout << (x >> 16 >> 16) << " " << (x >> 32) << endl;


gives: 0 1










share|improve this question

















  • 6




    See: stackoverflow.com/questions/19636539/… - not actually a duplicate question of this one, but certainly explains that it is undefined behaviour, and why. Short version: shift instructions in modern processors often won't shift by more than the register bit width.
    – davmac
    1 hour ago











  • guaranteing that the result is 0 may incur overhead that most of the time you dont need. Why would you shift by more than the number has bits?
    – user463035818
    1 hour ago






  • 1




    Some assembler instructions for rightshift have only 5 bit for the second operand. The first 5 bit of 32 are 0, so you have 1 >> 0 in some assembler languages.
    – mch
    1 hour ago










  • You can make your own: unsigned int right_shift(unsigned int x, int shift_amount) if (shift_amount >= std::numeric_limits<unsigned int>::digits) return 0; return x >> shift_amount; Notice the extra work to check the size? That's why >> by itself doesn't do that.
    – Eljay
    1 hour ago










  • At least on x86 shift instruction considers/masks only lower 5 bits of the value, i.e. it's basically x >> (num % 32) (same for <<). Implementing it as you want would require an expensive (relatively) branch to check if 0 < num < 32.
    – Dan M.
    1 hour ago















up vote
7
down vote

favorite
1












From cppreference.com:




For unsigned a and for signed a with nonnegative values, the value of
a >> b is the integer part of a/2b . For negative a, the value of a >>
b is implementation-defined (in most implementations, this performs
arithmetic right shift, so that the result remains negative).



In any case, if the value of the right operand is negative or is
greater or equal to the number of bits in the promoted left operand,
the behavior is undefined.




Why do we have an undefined behavior in case the right operand is greater or equal to the number of bits in the promoted left operand?

It seems to me that the result should be 0 (at least for unsigned/positive integers)...



In particular, with g++ (version 4.8.4, Ubuntu):



unsigned int x = 1;
cout << (x >> 16 >> 16) << " " << (x >> 32) << endl;


gives: 0 1










share|improve this question

















  • 6




    See: stackoverflow.com/questions/19636539/… - not actually a duplicate question of this one, but certainly explains that it is undefined behaviour, and why. Short version: shift instructions in modern processors often won't shift by more than the register bit width.
    – davmac
    1 hour ago











  • guaranteing that the result is 0 may incur overhead that most of the time you dont need. Why would you shift by more than the number has bits?
    – user463035818
    1 hour ago






  • 1




    Some assembler instructions for rightshift have only 5 bit for the second operand. The first 5 bit of 32 are 0, so you have 1 >> 0 in some assembler languages.
    – mch
    1 hour ago










  • You can make your own: unsigned int right_shift(unsigned int x, int shift_amount) if (shift_amount >= std::numeric_limits<unsigned int>::digits) return 0; return x >> shift_amount; Notice the extra work to check the size? That's why >> by itself doesn't do that.
    – Eljay
    1 hour ago










  • At least on x86 shift instruction considers/masks only lower 5 bits of the value, i.e. it's basically x >> (num % 32) (same for <<). Implementing it as you want would require an expensive (relatively) branch to check if 0 < num < 32.
    – Dan M.
    1 hour ago













up vote
7
down vote

favorite
1









up vote
7
down vote

favorite
1






1





From cppreference.com:




For unsigned a and for signed a with nonnegative values, the value of
a >> b is the integer part of a/2b . For negative a, the value of a >>
b is implementation-defined (in most implementations, this performs
arithmetic right shift, so that the result remains negative).



In any case, if the value of the right operand is negative or is
greater or equal to the number of bits in the promoted left operand,
the behavior is undefined.




Why do we have an undefined behavior in case the right operand is greater or equal to the number of bits in the promoted left operand?

It seems to me that the result should be 0 (at least for unsigned/positive integers)...



In particular, with g++ (version 4.8.4, Ubuntu):



unsigned int x = 1;
cout << (x >> 16 >> 16) << " " << (x >> 32) << endl;


gives: 0 1










share|improve this question













From cppreference.com:




For unsigned a and for signed a with nonnegative values, the value of
a >> b is the integer part of a/2b . For negative a, the value of a >>
b is implementation-defined (in most implementations, this performs
arithmetic right shift, so that the result remains negative).



In any case, if the value of the right operand is negative or is
greater or equal to the number of bits in the promoted left operand,
the behavior is undefined.




Why do we have an undefined behavior in case the right operand is greater or equal to the number of bits in the promoted left operand?

It seems to me that the result should be 0 (at least for unsigned/positive integers)...



In particular, with g++ (version 4.8.4, Ubuntu):



unsigned int x = 1;
cout << (x >> 16 >> 16) << " " << (x >> 32) << endl;


gives: 0 1







c++ bit-shift






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked 1 hour ago









R2B2

833815




833815







  • 6




    See: stackoverflow.com/questions/19636539/… - not actually a duplicate question of this one, but certainly explains that it is undefined behaviour, and why. Short version: shift instructions in modern processors often won't shift by more than the register bit width.
    – davmac
    1 hour ago











  • guaranteing that the result is 0 may incur overhead that most of the time you dont need. Why would you shift by more than the number has bits?
    – user463035818
    1 hour ago






  • 1




    Some assembler instructions for rightshift have only 5 bit for the second operand. The first 5 bit of 32 are 0, so you have 1 >> 0 in some assembler languages.
    – mch
    1 hour ago










  • You can make your own: unsigned int right_shift(unsigned int x, int shift_amount) if (shift_amount >= std::numeric_limits<unsigned int>::digits) return 0; return x >> shift_amount; Notice the extra work to check the size? That's why >> by itself doesn't do that.
    – Eljay
    1 hour ago










  • At least on x86 shift instruction considers/masks only lower 5 bits of the value, i.e. it's basically x >> (num % 32) (same for <<). Implementing it as you want would require an expensive (relatively) branch to check if 0 < num < 32.
    – Dan M.
    1 hour ago













  • 6




    See: stackoverflow.com/questions/19636539/… - not actually a duplicate question of this one, but certainly explains that it is undefined behaviour, and why. Short version: shift instructions in modern processors often won't shift by more than the register bit width.
    – davmac
    1 hour ago











  • guaranteing that the result is 0 may incur overhead that most of the time you dont need. Why would you shift by more than the number has bits?
    – user463035818
    1 hour ago






  • 1




    Some assembler instructions for rightshift have only 5 bit for the second operand. The first 5 bit of 32 are 0, so you have 1 >> 0 in some assembler languages.
    – mch
    1 hour ago










  • You can make your own: unsigned int right_shift(unsigned int x, int shift_amount) if (shift_amount >= std::numeric_limits<unsigned int>::digits) return 0; return x >> shift_amount; Notice the extra work to check the size? That's why >> by itself doesn't do that.
    – Eljay
    1 hour ago










  • At least on x86 shift instruction considers/masks only lower 5 bits of the value, i.e. it's basically x >> (num % 32) (same for <<). Implementing it as you want would require an expensive (relatively) branch to check if 0 < num < 32.
    – Dan M.
    1 hour ago








6




6




See: stackoverflow.com/questions/19636539/… - not actually a duplicate question of this one, but certainly explains that it is undefined behaviour, and why. Short version: shift instructions in modern processors often won't shift by more than the register bit width.
– davmac
1 hour ago





See: stackoverflow.com/questions/19636539/… - not actually a duplicate question of this one, but certainly explains that it is undefined behaviour, and why. Short version: shift instructions in modern processors often won't shift by more than the register bit width.
– davmac
1 hour ago













guaranteing that the result is 0 may incur overhead that most of the time you dont need. Why would you shift by more than the number has bits?
– user463035818
1 hour ago




guaranteing that the result is 0 may incur overhead that most of the time you dont need. Why would you shift by more than the number has bits?
– user463035818
1 hour ago




1




1




Some assembler instructions for rightshift have only 5 bit for the second operand. The first 5 bit of 32 are 0, so you have 1 >> 0 in some assembler languages.
– mch
1 hour ago




Some assembler instructions for rightshift have only 5 bit for the second operand. The first 5 bit of 32 are 0, so you have 1 >> 0 in some assembler languages.
– mch
1 hour ago












You can make your own: unsigned int right_shift(unsigned int x, int shift_amount) if (shift_amount >= std::numeric_limits<unsigned int>::digits) return 0; return x >> shift_amount; Notice the extra work to check the size? That's why >> by itself doesn't do that.
– Eljay
1 hour ago




You can make your own: unsigned int right_shift(unsigned int x, int shift_amount) if (shift_amount >= std::numeric_limits<unsigned int>::digits) return 0; return x >> shift_amount; Notice the extra work to check the size? That's why >> by itself doesn't do that.
– Eljay
1 hour ago












At least on x86 shift instruction considers/masks only lower 5 bits of the value, i.e. it's basically x >> (num % 32) (same for <<). Implementing it as you want would require an expensive (relatively) branch to check if 0 < num < 32.
– Dan M.
1 hour ago





At least on x86 shift instruction considers/masks only lower 5 bits of the value, i.e. it's basically x >> (num % 32) (same for <<). Implementing it as you want would require an expensive (relatively) branch to check if 0 < num < 32.
– Dan M.
1 hour ago













1 Answer
1






active

oldest

votes

















up vote
11
down vote













One of the goals of C++ is to allow for fast, efficient code, "close to the hardware". And on most hardware, an integer right shift or left shift can be implemented by a single opcode. The trouble is, different CPUs have different behavior in this case where the shift magnitude is more than the number of bits.



So if C++ mandated a particular behavior for shift operations, when producing code for a CPU whose opcode behavior doesn't match all the Standard requirements, compilers would need to insert checks and logic to make sure the result is as defined by the Standard in all cases. This would need to happen to almost all uses of the built-in shift operators, unless an optimizer can prove the corner case won't actually happen. The added checks and logic would potentially slow down the program.






share|improve this answer




















    Your Answer





    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52646507%2fundefined-behavior-of-right-shift-in-c%23new-answer', 'question_page');

    );

    Post as a guest






























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    11
    down vote













    One of the goals of C++ is to allow for fast, efficient code, "close to the hardware". And on most hardware, an integer right shift or left shift can be implemented by a single opcode. The trouble is, different CPUs have different behavior in this case where the shift magnitude is more than the number of bits.



    So if C++ mandated a particular behavior for shift operations, when producing code for a CPU whose opcode behavior doesn't match all the Standard requirements, compilers would need to insert checks and logic to make sure the result is as defined by the Standard in all cases. This would need to happen to almost all uses of the built-in shift operators, unless an optimizer can prove the corner case won't actually happen. The added checks and logic would potentially slow down the program.






    share|improve this answer
























      up vote
      11
      down vote













      One of the goals of C++ is to allow for fast, efficient code, "close to the hardware". And on most hardware, an integer right shift or left shift can be implemented by a single opcode. The trouble is, different CPUs have different behavior in this case where the shift magnitude is more than the number of bits.



      So if C++ mandated a particular behavior for shift operations, when producing code for a CPU whose opcode behavior doesn't match all the Standard requirements, compilers would need to insert checks and logic to make sure the result is as defined by the Standard in all cases. This would need to happen to almost all uses of the built-in shift operators, unless an optimizer can prove the corner case won't actually happen. The added checks and logic would potentially slow down the program.






      share|improve this answer






















        up vote
        11
        down vote










        up vote
        11
        down vote









        One of the goals of C++ is to allow for fast, efficient code, "close to the hardware". And on most hardware, an integer right shift or left shift can be implemented by a single opcode. The trouble is, different CPUs have different behavior in this case where the shift magnitude is more than the number of bits.



        So if C++ mandated a particular behavior for shift operations, when producing code for a CPU whose opcode behavior doesn't match all the Standard requirements, compilers would need to insert checks and logic to make sure the result is as defined by the Standard in all cases. This would need to happen to almost all uses of the built-in shift operators, unless an optimizer can prove the corner case won't actually happen. The added checks and logic would potentially slow down the program.






        share|improve this answer












        One of the goals of C++ is to allow for fast, efficient code, "close to the hardware". And on most hardware, an integer right shift or left shift can be implemented by a single opcode. The trouble is, different CPUs have different behavior in this case where the shift magnitude is more than the number of bits.



        So if C++ mandated a particular behavior for shift operations, when producing code for a CPU whose opcode behavior doesn't match all the Standard requirements, compilers would need to insert checks and logic to make sure the result is as defined by the Standard in all cases. This would need to happen to almost all uses of the built-in shift operators, unless an optimizer can prove the corner case won't actually happen. The added checks and logic would potentially slow down the program.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 1 hour ago









        aschepler

        50.4k570125




        50.4k570125



























             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52646507%2fundefined-behavior-of-right-shift-in-c%23new-answer', 'question_page');

            );

            Post as a guest













































































            Comments

            Popular posts from this blog

            What does second last employer means? [closed]

            Installing NextGIS Connect into QGIS 3?

            One-line joke