How can I perform arithmetic right shift in C in a portable way?

后端 未结 8 1722
挽巷
挽巷 2020-12-19 06:29

We are writing an emulator where we need sign propagating right shift. The emulated system uses 2\'s complement numbers.

I read that the >> operat

8条回答
  •  心在旅途
    2020-12-19 07:06

    Arithmetic right shift is equivalent to division by 2-to-the-number-you're- shifting-by, rounding towards zero if the divisor was nonnegative or towards infinity otherwise.

    Hence a generic portable arithmetic right-shift macro in GNU C could be:

    #if /*$auto*{{{*/ \
        __GNUC__>=7
        #define $let(L,R) __auto_type L = R
    #else
        #define $let(L,R) __typeof(R) L = R
    #endif //}}}
    #define $sar(X,By) /*{{{*/ \
        (__extension__({ \
           $let($sar_X,X); \
           $let($sar_divisor, ($sar_X*0+1)<<(By) ); \
           $sar__($sar_X, $sar_divisor);  \
        }))
        #define $sar__(X,Divisor) ((X)/(Divisor)+((X)%(Divisor)>=0?0:-1))
        /*}}}*/
    

    signedX >> shift often does the equivalent with less machine code (whether it does is implementation defined), and so you could have:

    #if (-2>>1==-1 && -2l>>1==-1 && -2ll>>1==-1) 
        //does signedX>>Shift do an arithmetic right shift?
    
        #define $sar(X,By) ((X)>>(By))
    #else
       //...the previous snippet...
    #endif
    

提交回复
热议问题