25

65529からunsigned int署名済みに変換しようとしていintます。私はこのようなキャストをしてみました:

unsigned int x = 65529;
int y = (int) x;

しかし、y-7を返す必要があるときにまだ65529を返しています。何故ですか?

4

9 に答える 9

37

あなたが期待intunsigned 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>
于 2011-11-29T20:30:35.173 に答える
6

古い質問だとは思いますが、良い質問なので、これはどうですか?

unsigned short int x = 65529U;
short int y = *(short int*)&x;

printf("%d\n", y);
于 2014-01-14T18:57:20.803 に答える
4

@神秘主義者はそれを手に入れました。ショートは通常 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 の補数表記を検索してください。基本は次のとおりです。

それでは、10 進数の 65529 を見てみましょう。FFF9h16 進数で表すことができます。バイナリで次のように表すこともできます。

11111111 11111001

を宣言するshort zz = 65529;と、コンパイラは 65529 を符号付きの値として解釈します。2 の補数表記では、最上位ビットは符号付きの値が正か負かを示します。この場合、トップビットが であることがわかります1ので、負の数として扱われます。そのため、出力され-7ます。

の場合、それは であるため、unsigned short符号は気にしませんunsigned。したがって%d、 を使用して出力すると、16 ビットすべてが使用されるため、 と解釈され65529ます。

于 2011-11-29T20:34:35.590 に答える
2

その理由を理解するには、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;
   //......
于 2015-03-21T11:13:09.360 に答える
1

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の拡張を想定)、除算は符号を維持しながら右にシフトします。

于 2011-11-29T20:31:43.160 に答える
0

タイプが16ビット幅であることを期待しています。intその場合、実際には負の値になります。ただし、おそらく32ビット幅であるため、符号付きintは65529を適切に表すことができます。これは、を印刷することで確認できますsizeof(int)

于 2011-11-29T20:31:52.050 に答える
0

上記のコメントに投稿された質問に答えるには、次のようなことを試してください。

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);
于 2011-11-29T20:35:14.543 に答える
0

これが古い質問であることは承知していますが、回答者が誤解した可能性があると思います。意図したのは、符号なし整数 (技術的には ) として受け取った 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 です。

于 2020-03-19T20:41:32.367 に答える
0

符号なし値の変換は正の数を表すために使用されるため、変換は最上位ビットを 0 に設定することで実行できます。したがって、プログラムはそれを 2 の補数値として解釈しません。1 つの注意点は、unsigned 型の max に近い数値の情報が失われることです。

template <typename TUnsigned, typename TSinged>
TSinged UnsignedToSigned(TUnsigned val)
{
    return val & ~(1 << ((sizeof(TUnsigned) * 8) - 1));
}
于 2019-03-01T06:46:54.467 に答える