7

16ビット整数の符号拡張を行う必要がありますが、何らかの理由で正しく機能していないようです。誰かがコードのどこにバグがあるのか​​教えてもらえますか?私は何時間もそれに取り組んできました。

int signExtension(int instr) {
    int value = (0x0000FFFF & instr);
    int mask = 0x00008000;
    int sign = (mask & instr) >> 15;
    if (sign == 1)
        value += 0xFFFF0000;
    return value;
}

命令(instr)は32ビットで、その中に16ビットの数値があります。

4

5 に答える 5

18

なぜ間違っているのですか:

int16_t s = -890;
int32_t i = s;  //this does the job, doesn't it?
于 2011-06-02T13:47:02.630 に答える
12

組み込み型を使用することの何が問題になっていますか?

int32_t signExtension(int32_t instr) {
    int16_t value = (int16_t)instr;
    return (int32_t)value;
}

またはさらに良い(これは、渡された場合に警告を生成する可能性がありますint32_t

int32_t signExtension(int16_t instr) {
    return (int32_t)instr;
}

または、すべての重要な点についてはsignExtension(value)((int32_t)(int16_t)value)

明らかに<stdint.h>int16_tint32_tデータ型を含める必要があります。

于 2011-06-02T13:49:27.640 に答える
8

何か他のものを探してこれにぶつかっただけで、多分少し遅れますが、多分それは他の誰かのために役立つでしょう。AFAIACすべてのCプログラマーは、アセンブラーのプログラミングから始める必要があります。

とにかく、符号拡張は提案よりもはるかに簡単です。符号付き変数を使用していることを確認してから、2シフトを使用してください。

long value;   // 32 bit storage
value=0xffff; // 16 bit 2's complement -1, value is now 0x0000ffff
value = ((value << 16) >> 16); // value is now 0xffffffff

変数が符号付きの場合、Cコンパイラは>>を符号を保持する算術ShiftRightに変換します。この動作はプラットフォームに依存しません。

したがって、値が0x1ffで始まるとすると、<< 16は値をSL(左シフト)するので、instrは0xff80になり、>> 16は値をASRするので、instrは0xffffになります。

マクロを本当に楽しみたい場合は、次のようなものを試してください(GCCでの構文はMSVCでは試していません)。

#include <stdio.h>

#define INT8 signed char
#define INT16 signed short
#define INT32 signed long
#define INT64 signed long long
#define SIGN_EXTEND(to, from, value) ((INT##to)((INT##to)(((INT##to)value) << (to - from)) >> (to - from)))

int main(int argc, char *argv[], char *envp[])
{
    INT16 value16 = 0x10f;
    INT32 value32 = 0x10f;
    printf("SIGN_EXTEND(8,3,6)=%i\n", SIGN_EXTEND(8,3,6));
    printf("LITERAL         SIGN_EXTEND(16,9,0x10f)=%i\n", SIGN_EXTEND(16,9,0x10f));
    printf("16 BIT VARIABLE SIGN_EXTEND(16,9,0x10f)=%i\n", SIGN_EXTEND(16,9,value16));
    printf("32 BIT VARIABLE SIGN_EXTEND(16,9,0x10f)=%i\n", SIGN_EXTEND(16,9,value32));

    return 0;
}

これにより、次の出力が生成されます。

SIGN_EXTEND(8,3,6)=-2
LITERAL         SIGN_EXTEND(16,9,0x10f)=-241
16 BIT VARIABLE SIGN_EXTEND(16,9,0x10f)=-241
32 BIT VARIABLE SIGN_EXTEND(16,9,0x10f)=-241
于 2012-11-06T18:48:15.787 に答える
6

試す:

int signExtension(int instr) {
    int value = (0x0000FFFF & instr);
    int mask = 0x00008000;
    if (mask & instr) {
        value += 0xFFFF0000;
    }
    return value;
}
于 2011-06-02T13:42:00.730 に答える
3

人々は、キャストと左シフトの後に算術右シフトが続くことを指摘しました。分岐を必要としない別の方法:

(0xffff & n ^ 0x8000) - 0x8000

上位16ビットがすでにゼロの場合:

(n ^ 0x8000) - 0x8000

• 「AggregateMagicAlgorithms、SignExtension」からのアイデアであるコミュニティウィキ

于 2018-08-22T00:40:48.043 に答える