7

次のスニペットがあるとします。

#include <stdio.h>

typedef signed long long int64;
typedef signed int int32;
typedef signed char int8;

int main()
{
    printf("%i\n", sizeof(int8));
    printf("%i\n", sizeof(int32));
    printf("%i\n", sizeof(int64));

    int8 a = 100;
    int8 b = 100;
    int32 c = a * b;
    printf("%i\n", c);

    int32 d = 1000000000;
    int32 e = 1000000000;
    int64 f = d * e;
    printf("%I64d\n", f);
}

MinGW GCC 3.4.5 での出力は (-O0) です。

1
4
8
10000
-1486618624

最初の乗算は、(アセンブラーの出力に従って) 内部で int32 にキャストされます。2 番目の乗算はキャストされません。プログラムが IA32 で実行されていたために結果が異なるのか、それとも C 標準のどこかで定義されているために結果が異なるのかはわかりません。それにもかかわらず、この正確な動作がどこか (ISO/IEC 9899?) で定義されているかどうかに興味があります。手動でキャストする必要がある理由とタイミングをよりよく理解したいからです (別のアーキテクチャからプログラムを移植する際に問題があります)。

4

4 に答える 4

7

C99標準では、などの二項演算子は。*より小さい整数型では動作しないと指定されていますint。これらのタイプの式はint、演算子が適用される前ににプロモートされます。6.3.1.4段落2および「整数拡張」という単語の多数の出現を参照してください。ただし、これは、コンパイラによって生成されたアセンブリ命令とは多少直交していますint。これは、コンパイラがより短い結果を計算できる場合でも高速であるためです(結果は、短いタイプのl値にすぐに格納されるため)。 、 例えば)。

とがタイプであるint64 f = d * e;場合、乗算は同じプロモーションルールに従って実行されます。オーバーフローは技術的に未定義の動作であり、ここでは2の補数の結果が得られますが、標準に従って何でも得ることができます。deintint

注:プロモーションルールでは、プロモーション時に符号付きタイプと符号なしタイプを区別します。規則は、型のすべての値を表すことができない場合をint除いて、より小さな型を昇格させることです。その場合はが使用されます。intunsigned int

于 2010-08-16T18:39:53.307 に答える
5

問題は、乗算が int32 * int32 であり、int32 として実行され、結果が int64 に割り当てられることです。でほぼ同じ効果が得られますdouble d = 3 / 2;。これは、整数除算を使用して 3 を 2 で除算し、1.0 を に割り当てdます。

重要な場合はいつでも、式または部分式の型に注意を払う必要があります。3.0 / 2これには、被乗数の 1 つを int64 または (私の例では)またはにキャストするなど、適切な演算が適切な型として計算されるようにする必要があります(float)3 / 2

于 2010-08-16T18:34:43.103 に答える
3

K&R(オリジナル)を読んでください。より大きなものにキャストされる(またはキャストされる)変数が含まれない限り、すべての整数演算は自然整数型で実行されます。charの演算は、32ビットにキャストされます。これは、そのアーキテクチャでは整数の自然なサイズであるためです。2つの32ビット整数の乗算は32ビットで行われます。これは、それをより大きなものにキャストするものがないためです(64ビット変数に割り当てるまでは手遅れです)。操作を64ビットで実行する場合は、一方または両方のintを64ビットにキャストします。

int64 f = (int64)d * e;
于 2010-08-16T18:39:43.623 に答える
2

a * bはintとして計算され、受信変数タイプ(たまたまint)にキャストされます。

d * eはintとして計算され、受信変数型(たまたまint64)にキャストされます。

型変数のいずれかがintよりも大きい(または浮動小数点である)場合は、その型が使用されます。ただし、乗算で使用されるすべての型がint以下であるため、intが使用されました。

于 2010-08-16T18:39:37.277 に答える