1
usigned int x=1;
signed int y = -1;
double z = y * x * 0.25;

Microsoft Visual Studio 10 C++ コンパイラを使用しています。z に -0.25 の値がないのはなぜですか? 逆アセンブルから見たように、signed int の乗算 (imul) を作成し、edx からの結果をスタックに配置し、unsigned int であるため 0! で拡張します。その後、FP 命令を使用して乗算します。

.............
imul        edx,dword ptr [ecx]  
mov         dword ptr [ebp-98h],edx  
mov         dword ptr [ebp-94h],0
fild        dword ptr [ebp-98h]  
fmul        qword ptr [__real@3fd0000000000000 (1402FB8h)]  
fstp        qword ptr [z]

signed * unsigned の乗算結果が unsigned と解釈されるのはなぜですか?

4

3 に答える 3

7

この式は、C と C++ の両方でy * x * 0.25関連付けられます。(y * x) * 0.25

unsigned intanと aを乗算すると、 C と C++ の両方の算術式の整数変換規則によりsigned int、両方のオペランドが に変換されunsigned int、結果もa になるため、 の結果はC と C++ の両方になります。unsigned inty * xUINT_MAX - 1

例を C または C++ としてコンパイルしているかどうかにかかわらず、例はコンパイラのバグを示しません。

于 2012-05-25T09:09:12.233 に答える
5

これは実際には仕様によるものです。C++11、5.9:

算術型または列挙型のオペランドを予期する多くの二項演算子は、同様の方法で変換を行い、結果の型を生成します。目的は、結果の型でもある共通の型を生成することです。このパターンは通常の算術変換と呼ばれ、次のように定義されます。

[...]

それ以外の場合、両方のオペランドで整数昇格 (4.5) が実行されます。次に、プロモートされたオペランドに次の規則が適用されます。

[...]

  • それ以外の場合、符号なし整数型を持つオペランドのランクが他のオペランドの型のランク以上である場合、符号付き整数型を持つオペランドは、符号なし整数型を持つオペランドの型に変換されます。

ここで の 2 つのオペランドy * xは signed と unsigned int で、整数変換ランクは同じです。そのためy、最終的に署名なしに変換されます。

于 2012-05-25T09:07:37.007 に答える
3

これは、標準の [expr] セクションで説明されています。

....

それ以外の場合、両方のオペランドで整数昇格 (4.5) が実行されます。次に、プロモートされたオペランドに次の規則が適用されます。

— 両方のオペランドが同じ型の場合、それ以上の変換は必要ありません。

— それ以外の場合、両方のオペランドが符号付き整数型であるか、両方が符号なし整数型である場合、整数変換ランクの小さい型のオペランドは、ランクの大きいオペランドの型に変換されます。

— それ以外の場合、符号なし整数型を持つオペランドのランクが他のオペランドの型のランク以上である場合、符号付き整数型を持つオペランドは、符号なし整数型を持つオペランドの型に変換されます。

式は左から右に評価されるため、y * x最初に計算されます。これには、同じランクの 2 つの整数型があり、1 つのオペランドは符号付きで、もう 1 つは符号なしです。したがって、標準の抜粋の最後の段落で説明されているように、符号付きの値は符号なしの値に変換されます。

于 2012-05-25T09:09:39.293 に答える