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
12
down vote

favorite
2












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

















  • 9




    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
    Oct 4 at 12:20







  • 2




    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
    Oct 4 at 12:21






  • 1




    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
    Oct 4 at 12:32






  • 1




    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.
    Oct 4 at 12:40







  • 2




    Long read, but super interesting if you're curious about undefined behaviour, especially the motivation behind it blog.regehr.org/archives/213
    – krsteeve
    Oct 4 at 19:59














up vote
12
down vote

favorite
2












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

















  • 9




    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
    Oct 4 at 12:20







  • 2




    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
    Oct 4 at 12:21






  • 1




    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
    Oct 4 at 12:32






  • 1




    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.
    Oct 4 at 12:40







  • 2




    Long read, but super interesting if you're curious about undefined behaviour, especially the motivation behind it blog.regehr.org/archives/213
    – krsteeve
    Oct 4 at 19:59












up vote
12
down vote

favorite
2









up vote
12
down vote

favorite
2






2





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 Oct 4 at 12:16









R2B2

861817




861817







  • 9




    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
    Oct 4 at 12:20







  • 2




    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
    Oct 4 at 12:21






  • 1




    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
    Oct 4 at 12:32






  • 1




    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.
    Oct 4 at 12:40







  • 2




    Long read, but super interesting if you're curious about undefined behaviour, especially the motivation behind it blog.regehr.org/archives/213
    – krsteeve
    Oct 4 at 19:59












  • 9




    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
    Oct 4 at 12:20







  • 2




    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
    Oct 4 at 12:21






  • 1




    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
    Oct 4 at 12:32






  • 1




    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.
    Oct 4 at 12:40







  • 2




    Long read, but super interesting if you're curious about undefined behaviour, especially the motivation behind it blog.regehr.org/archives/213
    – krsteeve
    Oct 4 at 19:59







9




9




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
Oct 4 at 12:20





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
Oct 4 at 12:20





2




2




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
Oct 4 at 12:21




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
Oct 4 at 12:21




1




1




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
Oct 4 at 12:32




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
Oct 4 at 12:32




1




1




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.
Oct 4 at 12:40





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.
Oct 4 at 12:40





2




2




Long read, but super interesting if you're curious about undefined behaviour, especially the motivation behind it blog.regehr.org/archives/213
– krsteeve
Oct 4 at 19:59




Long read, but super interesting if you're curious about undefined behaviour, especially the motivation behind it blog.regehr.org/archives/213
– krsteeve
Oct 4 at 19:59












2 Answers
2






active

oldest

votes

















up vote
29
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
















  • 6




    This doesn't explain why it isn't implementation-defined behavior, rather than completely undefined. That would also allow for "close to the hardware" implementations.
    – Ruslan
    Oct 4 at 16:22







  • 1




    Implementation-defined would mean that compilers handle it. If we're just passing stuff to the CPU it's not implementation defined. The makers of the compilers have no idea what happens. You could just check what a specific CPU does with the instructions and make a list of what happens for what CPU. Still it wouldn't be implementation-defined, it would be environment-defined.
    – xyious
    Oct 4 at 18:51










  • @Ruslan Implementation defined behavior lets the compiler choose from a set of options. For example, if the value of such a shift was implementation defined, a CPU would be forbidden from trapping it as an error.
    – Cort Ammon
    Oct 4 at 19:01






  • 1




    @CortAmmon right, if value were implementation-defined. But what about behavior? It could also be implementation-defined, and then trapping would be allowed, but would be required to be documented and remain consistent, unlike UB which can lead to logical paradoxes or whatnot.
    – Ruslan
    Oct 4 at 19:03







  • 1




    @xyious, compilers already have to be conscious of what CPUs do.
    – Paul Draper
    Oct 4 at 22:43

















up vote
1
down vote













To give a specific example, x86 trims the shift count to 5 bits (6 bits for 64-bit shifts), while ARM trims the shift count to 8 bits. With current C++ standard, compilers for both CPUs can implement shifts with a single opcode.



If the C++ standard were to define the outcome of shifts by more than the operand length in a particular way, compilers targeting at least one of the CPU families (and possibly both, if the outcome required by C++ wouldn't match either hardware implementation, like the behaviour you suggest) would have to implement each shift operation using branches which would produce the required result where the CPU opcode wouldn't.






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






























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    29
    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
















    • 6




      This doesn't explain why it isn't implementation-defined behavior, rather than completely undefined. That would also allow for "close to the hardware" implementations.
      – Ruslan
      Oct 4 at 16:22







    • 1




      Implementation-defined would mean that compilers handle it. If we're just passing stuff to the CPU it's not implementation defined. The makers of the compilers have no idea what happens. You could just check what a specific CPU does with the instructions and make a list of what happens for what CPU. Still it wouldn't be implementation-defined, it would be environment-defined.
      – xyious
      Oct 4 at 18:51










    • @Ruslan Implementation defined behavior lets the compiler choose from a set of options. For example, if the value of such a shift was implementation defined, a CPU would be forbidden from trapping it as an error.
      – Cort Ammon
      Oct 4 at 19:01






    • 1




      @CortAmmon right, if value were implementation-defined. But what about behavior? It could also be implementation-defined, and then trapping would be allowed, but would be required to be documented and remain consistent, unlike UB which can lead to logical paradoxes or whatnot.
      – Ruslan
      Oct 4 at 19:03







    • 1




      @xyious, compilers already have to be conscious of what CPUs do.
      – Paul Draper
      Oct 4 at 22:43














    up vote
    29
    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
















    • 6




      This doesn't explain why it isn't implementation-defined behavior, rather than completely undefined. That would also allow for "close to the hardware" implementations.
      – Ruslan
      Oct 4 at 16:22







    • 1




      Implementation-defined would mean that compilers handle it. If we're just passing stuff to the CPU it's not implementation defined. The makers of the compilers have no idea what happens. You could just check what a specific CPU does with the instructions and make a list of what happens for what CPU. Still it wouldn't be implementation-defined, it would be environment-defined.
      – xyious
      Oct 4 at 18:51










    • @Ruslan Implementation defined behavior lets the compiler choose from a set of options. For example, if the value of such a shift was implementation defined, a CPU would be forbidden from trapping it as an error.
      – Cort Ammon
      Oct 4 at 19:01






    • 1




      @CortAmmon right, if value were implementation-defined. But what about behavior? It could also be implementation-defined, and then trapping would be allowed, but would be required to be documented and remain consistent, unlike UB which can lead to logical paradoxes or whatnot.
      – Ruslan
      Oct 4 at 19:03







    • 1




      @xyious, compilers already have to be conscious of what CPUs do.
      – Paul Draper
      Oct 4 at 22:43












    up vote
    29
    down vote










    up vote
    29
    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 Oct 4 at 12:26









    aschepler

    50.5k571125




    50.5k571125







    • 6




      This doesn't explain why it isn't implementation-defined behavior, rather than completely undefined. That would also allow for "close to the hardware" implementations.
      – Ruslan
      Oct 4 at 16:22







    • 1




      Implementation-defined would mean that compilers handle it. If we're just passing stuff to the CPU it's not implementation defined. The makers of the compilers have no idea what happens. You could just check what a specific CPU does with the instructions and make a list of what happens for what CPU. Still it wouldn't be implementation-defined, it would be environment-defined.
      – xyious
      Oct 4 at 18:51










    • @Ruslan Implementation defined behavior lets the compiler choose from a set of options. For example, if the value of such a shift was implementation defined, a CPU would be forbidden from trapping it as an error.
      – Cort Ammon
      Oct 4 at 19:01






    • 1




      @CortAmmon right, if value were implementation-defined. But what about behavior? It could also be implementation-defined, and then trapping would be allowed, but would be required to be documented and remain consistent, unlike UB which can lead to logical paradoxes or whatnot.
      – Ruslan
      Oct 4 at 19:03







    • 1




      @xyious, compilers already have to be conscious of what CPUs do.
      – Paul Draper
      Oct 4 at 22:43












    • 6




      This doesn't explain why it isn't implementation-defined behavior, rather than completely undefined. That would also allow for "close to the hardware" implementations.
      – Ruslan
      Oct 4 at 16:22







    • 1




      Implementation-defined would mean that compilers handle it. If we're just passing stuff to the CPU it's not implementation defined. The makers of the compilers have no idea what happens. You could just check what a specific CPU does with the instructions and make a list of what happens for what CPU. Still it wouldn't be implementation-defined, it would be environment-defined.
      – xyious
      Oct 4 at 18:51










    • @Ruslan Implementation defined behavior lets the compiler choose from a set of options. For example, if the value of such a shift was implementation defined, a CPU would be forbidden from trapping it as an error.
      – Cort Ammon
      Oct 4 at 19:01






    • 1




      @CortAmmon right, if value were implementation-defined. But what about behavior? It could also be implementation-defined, and then trapping would be allowed, but would be required to be documented and remain consistent, unlike UB which can lead to logical paradoxes or whatnot.
      – Ruslan
      Oct 4 at 19:03







    • 1




      @xyious, compilers already have to be conscious of what CPUs do.
      – Paul Draper
      Oct 4 at 22:43







    6




    6




    This doesn't explain why it isn't implementation-defined behavior, rather than completely undefined. That would also allow for "close to the hardware" implementations.
    – Ruslan
    Oct 4 at 16:22





    This doesn't explain why it isn't implementation-defined behavior, rather than completely undefined. That would also allow for "close to the hardware" implementations.
    – Ruslan
    Oct 4 at 16:22





    1




    1




    Implementation-defined would mean that compilers handle it. If we're just passing stuff to the CPU it's not implementation defined. The makers of the compilers have no idea what happens. You could just check what a specific CPU does with the instructions and make a list of what happens for what CPU. Still it wouldn't be implementation-defined, it would be environment-defined.
    – xyious
    Oct 4 at 18:51




    Implementation-defined would mean that compilers handle it. If we're just passing stuff to the CPU it's not implementation defined. The makers of the compilers have no idea what happens. You could just check what a specific CPU does with the instructions and make a list of what happens for what CPU. Still it wouldn't be implementation-defined, it would be environment-defined.
    – xyious
    Oct 4 at 18:51












    @Ruslan Implementation defined behavior lets the compiler choose from a set of options. For example, if the value of such a shift was implementation defined, a CPU would be forbidden from trapping it as an error.
    – Cort Ammon
    Oct 4 at 19:01




    @Ruslan Implementation defined behavior lets the compiler choose from a set of options. For example, if the value of such a shift was implementation defined, a CPU would be forbidden from trapping it as an error.
    – Cort Ammon
    Oct 4 at 19:01




    1




    1




    @CortAmmon right, if value were implementation-defined. But what about behavior? It could also be implementation-defined, and then trapping would be allowed, but would be required to be documented and remain consistent, unlike UB which can lead to logical paradoxes or whatnot.
    – Ruslan
    Oct 4 at 19:03





    @CortAmmon right, if value were implementation-defined. But what about behavior? It could also be implementation-defined, and then trapping would be allowed, but would be required to be documented and remain consistent, unlike UB which can lead to logical paradoxes or whatnot.
    – Ruslan
    Oct 4 at 19:03





    1




    1




    @xyious, compilers already have to be conscious of what CPUs do.
    – Paul Draper
    Oct 4 at 22:43




    @xyious, compilers already have to be conscious of what CPUs do.
    – Paul Draper
    Oct 4 at 22:43












    up vote
    1
    down vote













    To give a specific example, x86 trims the shift count to 5 bits (6 bits for 64-bit shifts), while ARM trims the shift count to 8 bits. With current C++ standard, compilers for both CPUs can implement shifts with a single opcode.



    If the C++ standard were to define the outcome of shifts by more than the operand length in a particular way, compilers targeting at least one of the CPU families (and possibly both, if the outcome required by C++ wouldn't match either hardware implementation, like the behaviour you suggest) would have to implement each shift operation using branches which would produce the required result where the CPU opcode wouldn't.






    share|improve this answer
























      up vote
      1
      down vote













      To give a specific example, x86 trims the shift count to 5 bits (6 bits for 64-bit shifts), while ARM trims the shift count to 8 bits. With current C++ standard, compilers for both CPUs can implement shifts with a single opcode.



      If the C++ standard were to define the outcome of shifts by more than the operand length in a particular way, compilers targeting at least one of the CPU families (and possibly both, if the outcome required by C++ wouldn't match either hardware implementation, like the behaviour you suggest) would have to implement each shift operation using branches which would produce the required result where the CPU opcode wouldn't.






      share|improve this answer






















        up vote
        1
        down vote










        up vote
        1
        down vote









        To give a specific example, x86 trims the shift count to 5 bits (6 bits for 64-bit shifts), while ARM trims the shift count to 8 bits. With current C++ standard, compilers for both CPUs can implement shifts with a single opcode.



        If the C++ standard were to define the outcome of shifts by more than the operand length in a particular way, compilers targeting at least one of the CPU families (and possibly both, if the outcome required by C++ wouldn't match either hardware implementation, like the behaviour you suggest) would have to implement each shift operation using branches which would produce the required result where the CPU opcode wouldn't.






        share|improve this answer












        To give a specific example, x86 trims the shift count to 5 bits (6 bits for 64-bit shifts), while ARM trims the shift count to 8 bits. With current C++ standard, compilers for both CPUs can implement shifts with a single opcode.



        If the C++ standard were to define the outcome of shifts by more than the operand length in a particular way, compilers targeting at least one of the CPU families (and possibly both, if the outcome required by C++ wouldn't match either hardware implementation, like the behaviour you suggest) would have to implement each shift operation using branches which would produce the required result where the CPU opcode wouldn't.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 2 days ago









        Dmitry Grigoryev

        2,1141539




        2,1141539



























             

            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













































































            Popular posts from this blog

            How to check contact read email or not when send email to Individual?

            Bahrain

            Postfix configuration issue with fips on centos 7; mailgun relay