Skip to main content
Code Review

Return to Answer

replaced http://stackoverflow.com/ with https://stackoverflow.com/
Source Link

The left shift operator on signed types is tricky and will easily lead you to undefined behavior.

To put it formally, here is a quote from §6.5.7/4 Bitwise shift operators of a C11 draft, emphasis added:

The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 ×ばつ 2E2 , reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 ×ばつ 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

char is signed on a lot of platforms (likely including on the one you're testing). Therefore the following expression can fall foul of the "non-negative" constraint in the standardese above:

n <<= 1;

If n is negative, the expression has undefined behavior, even on common platforms with boring 8-bit (signed) chars.


There's a problem with the following too, on stranger implementations, related to the second constraint:

int mask = 1 << type_bits - 1;

On a platform where sizeof(int) == sizeof(char) (possible with e.g. CHAR_BITS==16 implementations, see What platforms have something other than 8-bit char? What platforms have something other than 8-bit char? for examples), that shift will push the 1 into the sign bit, which has undefined behavior: 1 x 2CHAR_BITS-1 is not representable (at least in 2's complement, 1's complement or sign/magnitude representations – they stop at 2CHAR_BITS-1-1. No idea if there are other representations that fulfill the C standard's conditions and would be able to represent that).


TLDR: unsigned types are the bit-twiddler's friend.

The left shift operator on signed types is tricky and will easily lead you to undefined behavior.

To put it formally, here is a quote from §6.5.7/4 Bitwise shift operators of a C11 draft, emphasis added:

The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 ×ばつ 2E2 , reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 ×ばつ 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

char is signed on a lot of platforms (likely including on the one you're testing). Therefore the following expression can fall foul of the "non-negative" constraint in the standardese above:

n <<= 1;

If n is negative, the expression has undefined behavior, even on common platforms with boring 8-bit (signed) chars.


There's a problem with the following too, on stranger implementations, related to the second constraint:

int mask = 1 << type_bits - 1;

On a platform where sizeof(int) == sizeof(char) (possible with e.g. CHAR_BITS==16 implementations, see What platforms have something other than 8-bit char? for examples), that shift will push the 1 into the sign bit, which has undefined behavior: 1 x 2CHAR_BITS-1 is not representable (at least in 2's complement, 1's complement or sign/magnitude representations – they stop at 2CHAR_BITS-1-1. No idea if there are other representations that fulfill the C standard's conditions and would be able to represent that).


TLDR: unsigned types are the bit-twiddler's friend.

The left shift operator on signed types is tricky and will easily lead you to undefined behavior.

To put it formally, here is a quote from §6.5.7/4 Bitwise shift operators of a C11 draft, emphasis added:

The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 ×ばつ 2E2 , reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 ×ばつ 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

char is signed on a lot of platforms (likely including on the one you're testing). Therefore the following expression can fall foul of the "non-negative" constraint in the standardese above:

n <<= 1;

If n is negative, the expression has undefined behavior, even on common platforms with boring 8-bit (signed) chars.


There's a problem with the following too, on stranger implementations, related to the second constraint:

int mask = 1 << type_bits - 1;

On a platform where sizeof(int) == sizeof(char) (possible with e.g. CHAR_BITS==16 implementations, see What platforms have something other than 8-bit char? for examples), that shift will push the 1 into the sign bit, which has undefined behavior: 1 x 2CHAR_BITS-1 is not representable (at least in 2's complement, 1's complement or sign/magnitude representations – they stop at 2CHAR_BITS-1-1. No idea if there are other representations that fulfill the C standard's conditions and would be able to represent that).


TLDR: unsigned types are the bit-twiddler's friend.

Source Link
Mat
  • 3k
  • 1
  • 22
  • 25

The left shift operator on signed types is tricky and will easily lead you to undefined behavior.

To put it formally, here is a quote from §6.5.7/4 Bitwise shift operators of a C11 draft, emphasis added:

The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 ×ばつ 2E2 , reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 ×ばつ 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

char is signed on a lot of platforms (likely including on the one you're testing). Therefore the following expression can fall foul of the "non-negative" constraint in the standardese above:

n <<= 1;

If n is negative, the expression has undefined behavior, even on common platforms with boring 8-bit (signed) chars.


There's a problem with the following too, on stranger implementations, related to the second constraint:

int mask = 1 << type_bits - 1;

On a platform where sizeof(int) == sizeof(char) (possible with e.g. CHAR_BITS==16 implementations, see What platforms have something other than 8-bit char? for examples), that shift will push the 1 into the sign bit, which has undefined behavior: 1 x 2CHAR_BITS-1 is not representable (at least in 2's complement, 1's complement or sign/magnitude representations – they stop at 2CHAR_BITS-1-1. No idea if there are other representations that fulfill the C standard's conditions and would be able to represent that).


TLDR: unsigned types are the bit-twiddler's friend.

lang-c

AltStyle によって変換されたページ (->オリジナル) /