C言語でのシフト演算

久々にプログラミングの話。まあ、C言語でのこんなコードがあったと思いねぇ。

unsigned int data = 0xFEDC0000;
unsigned int x;
 ...
x = (data >> 16) & 0x0000FFFF;

不思議に思ったのは、最後の"& 0x0000FFFF;"のところ。何故、上部16ビットの確保のために、シフトで十分なところをわざわざマスクをかけているのか。
ちょっとググってみると、C言語においてシフト演算は論理シフトか算術シフトか決められてないそうな。ということで、論理/算術どちらでも対応できるようにマスクが掛けられているんですな。
ちなみに上記のコード、論理シフトになります。Visual C++ 6.0での話ですが、該当部をコンパイルすると

    ;; data >> 16
    shr eax, 16    ;;論理右シフト

と、なります。(注:正確なコンパイル結果ではありません。論理シフトになったよ、と言いたいだけ。)
何故か?恐らく変数dataの型がunsignedだからだと思われます。変数dataをsigned int型に変えると、こちらは

    ;; data >> 16
    sar eax, 16    ;;算術右シフト

になりました。(注:正確なコンパイル結果ではありません。signedだと算術シフトになったよ、と言いたいだけ。)


うん、やっぱりこういうことが理解できるようになったのだから、アセンブラに食指を伸ばしておいて正解だった。