Right shifting a signed quantity will fill with bit signs ("arithmetic shift") on some machines and with 0-bits ("logical shift") on others.
— The C Programming Language, Kernighan and Ritchie
Signed right shifts have implementation-defined behaviour¹.
Common implementations choose to fill with sign bits (gcc¹, clang², msvc³).
That is a signed arithmetic right shift (sar).
Functions in sar.c twiddle bits to provide portable arithmetic right shifts.
sari(-5, 1) == -3; /* true */They compile to small, branchless instructions. See for yourself on the Compiler Explorer.
Standard integer types are supported for pedantic C99 and C++11.
#include "stdint.h" /* optional */ #include "sar.c" sari(-63, 3); /* -8 */ sarl(-0x200000000L, 1); /* -0x100000000L */ sarfast32(-0xDECAF, 8); /* -0xDED */ sar8(15, 2); /* 3 */Arithmetic right shift functions defined by "sar.c" are of the form
static inline type sar##(type m, char n);where type is any of:
signed char /* sarc */ short /* sars */ int /* sari */ long /* sarl */ long long /* sarll */ /* if stdint.h is included */ int_fast8_t /* sarfast8 */ int_fast16_t /* sarfast16 */ int_fast32_t /* sarfast32 */ int_fast64_t /* sarfast64 */ int_least8_t /* sarleast8 */ int_least16_t /* sarleast16 */ int_least32_t /* sarleast32 */ int_least64_t /* sarleast64 */ intmax_t /* sarmax */ /* optionally included in stdint.h */ int8_t /* sar8 */ int16_t /* sar16 */ int32_t /* sar32 */ int64_t /* sar64 */ intptr_t /* sarptr */The following macros are also defined.
/* For the include guard. */ #define SAR_C /* Macro to define the sar## function bodies. Not standalone. */ #define SARBODY(type, utype)Alternatives which force logical shifts, then correct them back, are defined in "saru.c" with the prefixes saru## and SARU.
make¹ "The result of E1 >> E2 is E1 right-shifted E2 bit positions. ... If E1 has a signed type and a negative value, the resulting value is implementation-defined.", ISO C N2176 6.5.7, p84-85
² "Signed ‘>>’ acts on negative numbers by sign extension.", GCC C Implementation-Defined Behavior 4.5 Integers
³ "GCC is currently the defacto-standard open source compiler today", Clang - Features and Goals
⁴ "the Microsoft C++ compiler uses the sign bit to fill vacated bit positions" Left Shift and Right Shift Operators (>> and <<)