#include "stdio.h"
int main()
{
int x = -13701;
unsigned int y = 3;
signed short z = x / y;
printf("z = %d\n", z);
return 0;
}
答えは -4567 になると思います。「z = 17278」を取得しています。これらの数値を昇格すると 17278 になるのはなぜですか?
これをCode Padで実行しました。
#include "stdio.h"
int main()
{
int x = -13701;
unsigned int y = 3;
signed short z = x / y;
printf("z = %d\n", z);
return 0;
}
答えは -4567 になると思います。「z = 17278」を取得しています。これらの数値を昇格すると 17278 になるのはなぜですか?
これをCode Padで実行しました。
非表示の型変換は次のとおりです。
signed short z = (signed short) (((unsigned int) x) / y);
署名された型と署名されていない型を混在させると、署名されていない型が優先されます。x
に変換されunsigned int
、3 で除算され、その結果が (signed) にダウンコンバートされshort
ます。32 ビット整数の場合:
(unsigned) -13701 == (unsigned) 0xFFFFCA7B // Bit pattern
(unsigned) 0xFFFFCA7B == (unsigned) 4294953595 // Re-interpret as unsigned
(unsigned) 4294953595 / 3 == (unsigned) 1431651198 // Divide by 3
(unsigned) 1431651198 == (unsigned) 0x5555437E // Bit pattern of that result
(short) 0x5555437E == (short) 0x437E // Strip high 16 bits
(short) 0x437E == (short) 17278 // Re-interpret as short
ちなみにsigned
キーワードは不要です。signed short
は長い言い方ですshort
。明示を必要とする唯一の型signed
はchar
. char
プラットフォームに応じて、署名付きまたは未署名にすることができます。他のすべてのタイプは、デフォルトで常に署名されています。
短い答え: 師団は最初に に昇格x
しunsigned
ます。その場合にのみ、結果が にキャストされますsigned short
。
長い答え:この SO スレッドを読んでください。
問題はunsigned int y
. 確かに、x/y
無署名になります。それはで動作します:
#include "stdio.h"
int main()
{
int x = -13701;
signed int y = 3;
signed short z = x / y;
printf("z = %d\n", z);
return 0;
}
加算および乗算算術演算で「大きな」符号付き値と符号なし値を混合するたびに、符号なし型が「勝ち」、評価は符号なし型の領域で実行されます (「大きな」とはint
、より大きいことを意味します)。元の符号付きの値が負の場合、符号付きから符号なしへの変換の規則に従って、最初に符号なしの正の値に変換されます。あなたの場合-13701
は にUINT_MAX + 1 - 13701
なり、結果は配当として使用されます。
一般的な 32 ビットint
プラットフォームでの符号付きから符号なしへの変換の結果は、符号なしの値になることに注意してください4294953595
。で除算する3
と、 が得られます1431651198
。short
この値は、16 ビットshort
型のプラットフォームで強制的にオブジェクトにするには大きすぎます。それを行おうとすると、実装定義の動作が発生します。したがって、プラットフォームのプロパティが私の仮定と同じである場合、コードは実装定義の動作を生成します。正式に言えば、得られる「無意味な」17278
値は、その実装定義の動作の特定の現れにすぎません。オーバーフロー チェックを有効にしてコードをコンパイルした場合 (コンパイラがサポートしている場合)、代入でトラップされる可能性があります。