Undefined behavior of right-shift in C++
Clash Royale CLAN TAG#URR8PPP
up vote
12
down vote
favorite
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
 |Â
show 2 more comments
up vote
12
down vote
favorite
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
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 onx86
shift instruction considers/masks only lower5
bits of the value, i.e. it's basicallyx >> (num % 32)
(same for<<
). Implementing it as you want would require an expensive (relatively) branch to check if0 < 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
 |Â
show 2 more comments
up vote
12
down vote
favorite
up vote
12
down vote
favorite
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
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
c++ bit-shift
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 onx86
shift instruction considers/masks only lower5
bits of the value, i.e. it's basicallyx >> (num % 32)
(same for<<
). Implementing it as you want would require an expensive (relatively) branch to check if0 < 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
 |Â
show 2 more comments
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 onx86
shift instruction considers/masks only lower5
bits of the value, i.e. it's basicallyx >> (num % 32)
(same for<<
). Implementing it as you want would require an expensive (relatively) branch to check if0 < 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
 |Â
show 2 more comments
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.
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
 |Â
show 5 more comments
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.
add a comment |Â
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.
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
 |Â
show 5 more comments
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.
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
 |Â
show 5 more comments
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.
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.
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
 |Â
show 5 more comments
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
 |Â
show 5 more comments
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.
add a comment |Â
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.
add a comment |Â
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.
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.
answered 2 days ago
Dmitry Grigoryev
2,1141539
2,1141539
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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 lower5
bits of the value, i.e. it's basicallyx >> (num % 32)
(same for<<
). Implementing it as you want would require an expensive (relatively) branch to check if0 < 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