0

The C99 spec states:

The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2^E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.

I'm curious to know, which implementations/compilers will not treat a signed E1 >> 31 as a bunch of 11111....?

4
  • 3
    A few whose -1 is not 1111...., and a lot whose int is not 32 bits. Commented Mar 30, 2016 at 14:33
  • 1
    Note: Don't use an outdated version of the standard. C standard is C11, not C99. Said that, the text is very clear. Don't rely on it if you want your code portable. Note the shift can also invoke undefined behaviour. See 6.5.7p3 in the standard (i.e. the only valid version). Commented Mar 30, 2016 at 14:43
  • Also many 32-bit, twos-complement implementations that ignore the signedness and produce 1 as the result. The standard is in fact carefully worded to avoid specifying whether >> performs an arithmetic shift or a logical shift. Commented Mar 30, 2016 at 14:49
  • Possible duplicate of Signed right shift: which compiler use logical shift Commented Apr 14, 2019 at 8:59

2 Answers 2

2

Most embedded compilers for microcontrollers tend to favour logical shift (shift in zeroes) instead of arithmetic shift (shift in the sign bit).

This is probably because signed numbers are somewhat rare in embedded systems, since such programming is much closer to the hardware and further away from users, than for example desktop programming with screens.

Signed numbers is nothing but user presentation after all. If you have no need to print numbers to a user, then you don't need signed numbers very often at all.

And of course, it doesn't really make any sense to use shift on signed numbers to begin with. I have never in my programming career encountered a scenario when I had needed to do that. Meaning in most cases, such shifts are just accidental bugs.

Sign up to request clarification or add additional context in comments.

4 Comments

@Lundin I'm working with some crypto code which takes advantage of arithmetic right shifting as a way to remove an if statement. Thanks for your answer.
@MarkP Oh but then you definitely need to reconsider that algorithm, if portability is important.
@Lundin Yes, that's the heart of the issue. It's unlikely that this code will run on microcontrollers. The main concern was that there are big computers out there that cannot handle this situation.
@Lundin Even if signed integers are 2's complement, and right shift is an arithmetic right shift, dividing by two is not the same as right shift when the value being operated on is both negative and odd. Division truncates towards zero, but arithmetic right shift truncates towards minus infinity.
0

You can simulate a signed, 2's complement arithmetic right shift using unsigned types without the use of if statements. For example:

#include <limits.h> unsigned int asr(unsigned int x, unsigned int shift) { return (x >> shift) | -((x & ~(UINT_MAX >> 1)) >> shift); } 

You might need to use a different unsigned type and its associated max value in your code.

2 Comments

What has this to do with the question?
@Lundin It's related to the question, though doesn't answer the question directly. It's hard to put code in a normal comment. It kind of answers it as an X Y problem. If you can't rely on >> to do an arithmetic right shift, how can it be done portably?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.