署名されていないintを署名したint cに変換します
-
25-10-2019 - |
質問
私は変換しようとしています 65529
から unsigned int
署名済み int
. 。私はこのようなキャストをやってみました:
unsigned int x = 65529;
int y = (int) x;
しかし y
-7を返す必要がある場合、まだ65529を返しています。何故ですか?
解決
あなたが期待しているようです int
と unsigned int
16ビットの整数になること。どうやらそうではありません。おそらく、それは32ビットの整数であり、あなたが期待しているラップアラウンドを避けるのに十分な大きさです。
これを行うための完全にcに準拠した方法はないことに注意してください。なぜなら、範囲外の値のために署名されていない/符号なしのキャストが実装定義であるためです。しかし、これはまだほとんどの場合に機能します。
unsigned int x = 65529;
int y = (short) x; // If short is a 16-bit integer.
または、または:
unsigned int x = 65529;
int y = (int16_t) x; // This is defined in <stdint.h>
他のヒント
私はそれが古い質問であることを知っていますが、それは良いことです、それでこれはどうですか?
unsigned short int x = 65529U;
short int y = *(short int*)&x;
printf("%d\n", y);
@MySticialはそれを手に入れました。ショートは通常16ビットで、答えを説明します。
int main()
{
unsigned int x = 65529;
int y = (int) x;
printf("%d\n", y);
unsigned short z = 65529;
short zz = (short)z;
printf("%d\n", zz);
}
65529
-7
Press any key to continue . . .
もう少し詳細。署名された番号がメモリに保存される方法がすべてです。詳細については、2つの補完表記を検索しますが、基本は次のとおりです。
それでは、65529小数を見てみましょう。として表すことができます FFF9h
16進数。それをバイナリで次のように表現することもできます。
11111111 11111001
宣言するとき short zz = 65529;
, 、コンパイラは署名された値として65529を解釈します。 2つの補完表記では、上部が署名された値が正または負であるかどうかを意味します。この場合、トップビットが 1
, 、したがって、それは負の数として扱われます。それが印刷する理由です -7
.
のために unsigned short
, 、私たちはそれがあるのでサインを気にしません unsigned
. 。したがって、使用して印刷するとき %d
, 、16ビットすべてを使用しているので、 65529
.
理由を理解するには、CPUが2つの補完を使用して署名された番号を表していることを知る必要があります(すべてではなく、多く)。
byte n = 1; //0000 0001 = 1
n = ~n + 1; //1111 1110 + 0000 0001 = 1111 1111 = -1
また、CPUに応じて、型int intおよびunsigned intのサイズが異なる場合があります。このような特定のことをするとき:
#include <stdint.h>
int8_t ibyte;
uint8_t ubyte;
int16_t iword;
//......
値65529Uと-7の表現は、16ビットINTで同一です。ビットの解釈のみが異なります。
より大きなINTおよびこれらの値の場合、拡張に署名する必要があります。 1つの方法は、論理操作を使用することです
int y = (int )(x | 0xffff0000u); // assumes 16 to 32 extension, x is > 32767
速度が問題ではない場合、またはプロセッサで除算が高速な場合、
int y = ((int ) (x * 65536u)) / 65536;
マルチシフトは左16ビット(繰り返しますが、16〜32の拡張を想定しています)、微分は標識を維持してシフトします。
あなたはあなたのことを期待しています int
タイプは16ビット幅です。その場合、実際には負の値が得られます。しかし、おそらくそれは32ビット幅であるため、署名されています int
65529を表現できます。印刷してこれを確認できます sizeof(int)
.
上記のコメントに投稿された質問に答えるには - このようなものを試してください:
unsigned short int x = 65529U;
short int y = (short int)x;
printf("%d\n", y);
また
unsigned short int x = 65529U;
short int y = 0;
memcpy(&y, &x, sizeof(short int);
printf("%d\n", y);
署名されていない値を変換するため、正の数値を表すために使用するため、最も重要なビットを0に設定することで実行できます。したがって、プログラムはそれを2つの補数値として解釈しません。 1つの警告は、これにより、署名されていないタイプの最大値に近い数値の情報が失われることです。
template <typename TUnsigned, typename TSinged>
TSinged UnsignedToSigned(TUnsigned val)
{
return val & ~(1 << ((sizeof(TUnsigned) * 8) - 1));
}