9

次のcコードを書きました:

#include <stdio.h>

int main () {
  printf("%d\n", -1 >> 8);
  return 0;
}

-m32 フラグを使用して、x86_64 で gcc 4.6.3 でこのコードをコンパイルします。予想どおり-1が出力されます。シフトは2の補数表現を使用して算術的に発生し、-1になります。

今、代わりに書くと

printf("%d\n", 0xFFFFFFFF >> 8);

私は 16777215 を取得します。この定数は int (符号付き) として解釈され、シフトは算術演算であり、結果は再び -1 になると予想していました。私は最新の C 標準に目を通しましたが、なぜそうなのか理解できないようです。何か案は?

4

2 に答える 2

17

C99 標準 (6.4.4.1) によると、16 進定数は、このリストでそれらを表すことができる最初の型になります。

int
unsigned int
long int
unsigned long int
long long int
unsigned long long int

16 進リテラル0xFFFFFFFFint(~の値-0x80000000を保持できる0x7FFFFFFF) には適合しませんが、 には適合するunsigned intため、その型は符号なしになります。0xFFFFFFFF符号なしの値を 8だけ右シフトすると、が得られ16777215ます。

于 2012-09-19T17:24:59.513 に答える
11

装飾されていない整数リテラルは、10 進数かどうかによって型が異なります (C11 では 6.4.4.1/5、C++11 では表 6)。

  • 10 進リテラル、つまり[1-9][0-9]*は常に符号付きです。

  • 16 進数および 8 進数のリテラルは、符号付きまたは符号なしのいずれかです。値が符号付きの型には大きすぎるが、同じ幅の符号なしの型に収まるほど小さい場合は、符号なしになります。(これは、16 進定数に起こることです。)

負の整数の右シフトは実装定義であり、たまたま符号拡張が発生します。符号なし値の右シフトは単純な 2 除算です。

于 2012-09-19T17:17:47.790 に答える