3

ここではVisualC++ 2008(9.x)を使用しており、IDIVではなくDIVを生成するコンパイラーに遭遇したときに固定小数点値を準備していました。コードを小さな断片に折りたたんで、正確に再現しました。

short a = -255;
short divisor16 = 640; // unsigned, 16-bit
unsigned int divisor32 = 640; // unsigned, 32-bit
unsigned short s_divisor16 = 640; // signed, 16-bit
int s_divisor32 = 640; // signed, 32-bit
int16_t test1 = (a<<8)/divisor16; // == -102, generates IDIV -> OK
int16_t test2 = (a<<8)/s_divisor16; // == -102, generates IDIV -> OK
int16_t test3 = (a<<8)/divisor32; // == bogus, generates DIV -> FAIL!
int16_t test4 = (a<<8)/s_divisor32; // == -102, generates IDIV -> OK

int bitte_ein_breakpoint=1;

簡単な分解で煩わされることはありません。

ショートカットを使用して除数の型(関数パラメーター、unsigned int numPixels)を変更する代わりに、3番目の(test3)の場合、コンパイラーがIDIVよりもDIVを選択するのはなぜですか?符号なし16ビット除数であり、とにかく符号なし演算を必要とするものは実際にはありません。少なくともそれは私が思うことであり、私が間違っていることを願っています:)

4

2 に答える 2

7

演算子に対して生成されるコードは/、オペランドによって異なります。

最初に、各オペランドに対して整数昇格が実行されるため(ISO C99、6.5.7p3)、式の型は であり、演算はで(a << 8)あり、結果は.intint << intint

現在、次の 4 つの式があります。

  1. int / short: 右辺が に昇格されるintため、idiv命令です。
  2. int / unsigned short: 右辺が に昇格されるintため、idiv命令です。
  3. int / unsigned int:左辺が に昇格されるunsigned intため、div命令です。
  4. int / int: 何も昇格されないため、idiv命令は適切です。

整数昇格は、ISO C99 6.3.1.1p3 で定義されています。

intが元の型のすべての値を表すことができる場合、値はint;に変換されます。それ以外の場合は、に変換されますunsigned int。これらは整数プロモーションと呼ばれます。.

于 2011-08-20T12:41:55.773 に答える
1

負の値を左シフトすると、未定義の動作が発生します。したがって、このシナリオでコンパイラが選択したことから多くの結論を引き出すことができるかどうかはわかりません。

于 2011-08-20T12:41:08.037 に答える