移植性が(ほとんど)あり性能問題が無い(かもしれない)、負の値に対応した算術右シフトのCコード
普通は、自分のマシンでどのようなコードが生成されるかを確認して、うまくいっていればそれで良しとする所ですが、右シフトは凝ったコードを書こうとするCプログラマにとって悩みの種です。
しかし、手元の環境( FreeBSD clang version 3.4.1 )で、次のような、「あらゆる環境で2の補数マシンをエミュレーションするコード」を、
(追記: ビットパターンが 0x800...000 のようになるような最小の負の値の時には、このコードでも「未定義」を踏んでいます)と思ったのですが、最初に +1 することで回避してますねコレ。それでも未定義に落とせる抜け穴あるかな?
int signed_shift_right(int x, unsigned a) { return ( (x < 0) ? (-(-(x+1)>>a)-1) : (x >> a) ) ; }
-O3 オプション付きでコンパイルしてみたところ、次のように「完全に」最適化されました。
$ clang -W -Wall -Wextra -pedantic -O3 -S signed_shift_right.c $ cat signed_shift_right.s .file "signed_shift_right.c" .text .globl signed_shift_right .align 16, 0x90 .type signed_shift_right,@function signed_shift_right: # @signed_shift_right .cfi_startproc # BB#0: pushq %rbp .Ltmp2: .cfi_def_cfa_offset 16 .Ltmp3: .cfi_offset %rbp, -16 movq %rsp, %rbp .Ltmp4: .cfi_def_cfa_register %rbp movb %sil, %cl sarl %cl, %edi movl %edi, %eax popq %rbp ret .Ltmp5: .size signed_shift_right, .Ltmp5-signed_shift_right .cfi_endproc .ident "FreeBSD clang version 3.4.1 (tags/RELEASE_34/dot1-final 208032) 20140512" .section ".note.GNU-stack","",@progbits
static inline を付けて、インライン展開まで効けば、おそらく完全にオーバヘッド0のコードが生成されるものと思われます。