65529
からunsigned int
署名済みに変換しようとしていint
ます。私はこのようなキャストをしてみました:
unsigned int x = 65529;
int y = (int) x;
しかし、y
-7を返す必要があるときにまだ65529を返しています。何故ですか?
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);
@神秘主義者はそれを手に入れました。ショートは通常 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 . . .
それでは、10 進数の 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
また、int型とunsigned int型は、CPUによってサイズが異なる場合があります。このような特定のことをするとき:
#include <stdint.h>
int8_t ibyte;
uint8_t ubyte;
int16_t iword;
//......
65529uと-7の値の表現は、16ビットintの場合と同じです。ビットの解釈のみが異なります。
より大きなintとこれらの値の場合、extendに署名する必要があります。1つの方法は、論理演算を使用することです
int y = (int )(x | 0xffff0000u); // assumes 16 to 32 extension, x is > 32767
速度が問題にならない場合、またはプロセッサで除算が速い場合は、
int y = ((int ) (x * 65536u)) / 65536;
乗算は左に16ビットシフトし(ここでも、16から32の拡張を想定)、除算は符号を維持しながら右にシフトします。
タイプが16ビット幅であることを期待しています。int
その場合、実際には負の値になります。ただし、おそらく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);
これが古い質問であることは承知していますが、回答者が誤解した可能性があると思います。意図したのは、符号なし整数 (技術的には ) として受け取った 16 桁のビット シーケンスを符号付き整数に変換することだったと思いますunsigned short
。これは、ネットワークから受信したものをネットワーク バイト オーダーからホスト バイト オーダーに変換する必要がある場合に発生する可能性があります (最近発生しました)。その場合、ユニオンを使用します。
unsigned short value_from_network;
unsigned short host_val = ntohs(value_from_network);
// Now suppose host_val is 65529.
union SignedUnsigned {
short s_int;
unsigned short us_int;
};
SignedUnsigned su;
su.us_int = host_val;
short minus_seven = su.s_int;
そして今minus_seven
、値は -7 です。
符号なし値の変換は正の数を表すために使用されるため、変換は最上位ビットを 0 に設定することで実行できます。したがって、プログラムはそれを 2 の補数値として解釈しません。1 つの注意点は、unsigned 型の max に近い数値の情報が失われることです。
template <typename TUnsigned, typename TSinged>
TSinged UnsignedToSigned(TUnsigned val)
{
return val & ~(1 << ((sizeof(TUnsigned) * 8) - 1));
}