C ユーザーズガイド

符号の拡張

型の変換と拡張規則はいくぶん曖昧ですから、64 ビットコンパイル環境への移行で、符号の拡張はよく問題になります。符号の拡張の問題を避けるには、明示的な型変換を使用して、意図した結果を得られるようにしてください。

符号の拡張が発生する理由を理解するには、ANSI C の変換規則の知識が役立ちます。32 ビットと 64 ビットコンパイル環境間で最大の符号拡張問題を引き起こすと思われる変換規則は、次の処理で適用されます。

次のコードを 64 ビットプログラムとしてコンパイルすると、addra.base の両方が符号なしの型であっても、addr 変数は符号拡張されます。


%cat test.c
struct foo {
unsigned int base:19, rehash:13;  
};

main(int argc, char *argv[]) 
{
  struct foo a;
  unsigned long addr;

  a.base = 0x40000;
  addr = a.base << 13;  /* ここで符号拡張する ! */
  printf("addr 0x%lx¥n", addr);

  addr = (unsigned int)(a.base << 13); /* 符号拡張しない ! */
  printf("addr 0x%lx¥n", addr);
}

ここで符号拡張が起きるのは、次のように変換規則が適用されるためです。

同じ例を 32 ビットプログラムとしてコンパイルすると、符号拡張はまったく表示されません。

変換規則の詳細については、ANSI C 規格の仕様書を参照してください。この規格には通常の演算変換や整数定数に関する有用な規則も規定されています。