0

32 ビットまたは 24 ビットの符号付き (2 の補数) 16 進文字列を long int に変換する関数が必要です。(long int のサイズに関係なく) 32 ビット マシンと 64 ビット マシンの両方で動作し、マシンが 2 の補数マシンであるかどうかに関係なく動作する必要があります。

解決:

long int hex2li (char hexStr[], int signedHex)
{
   int bits = strlen (hexStr) * 4;

   char *pEnd;
   long long int result = strtoll (hexStr, &pEnd, 16);

   if (pEnd[0] == '\0')
   {
      if (signedHex)
      {
         if (result >= (1LL << (bits - 1))) result -= (1LL << bits);
      }

      return (long int) result;
   }

   return LONG_MIN;
}
4

5 に答える 5

5

24ビット文字列の場合:

16進文字列を解析すると、標準strtol関数はそれを範囲内の符号なしの値として読み取ります0 -> 2^24 - 1

範囲0 -> 2^23 - 1は正しいですが、次のように実行できる単純な減算である範囲2^23 -> 2^24 - 1をマップする必要があります。-2^23 -> -1

if (result >= (1L << 23))
    result -= (1L << 24);

同じ手法を使用して32ビット文字列を変換するには、減算を実行するために、符号付き型で完全な32ビット符号なし整数を表すことができる中間型を使用する必要があります。Along long intは64ビットであることが保証されているため、これを使用できます。

例えば

long int ParseHexStr(const char *in, int bits)
{
    char* endptr;
    long long int result;

    result = strtoll(in, &endptr, 16);

    /*
    ** TODO - error checking, e.g. check endptr != in
    **  Also check for range errors, signalled by LLONG_MIN
    **  LLONG_MAX and a errno == ERANGE.
    */

    if (result >= (1LL << (bits - 1))
        result -= (1LL << bits);

    return result;
}
于 2010-05-06T15:00:46.967 に答える
1

この比較は間違っています:if (toupper (string[0]) == 'F')

MSBが設定されている値については、符号拡張する必要があるため、次のようになります。

if(strchr("89ABCDEF", toupper(string[0])) != NULL)

于 2010-05-06T14:45:24.173 に答える
1

SIGN_EXTEND次のようなマクロがあります。

#define SIGN_EXTEND(X, SignBit, Type) \
    (((Type) ((X) << (8 * sizeof(Type) - (SignBit) - 1))) >> \
     (8 * sizeof(Type) - (SignBit) - 1))

>>符号ビットが設定されている場合、入力を 1 で埋める演算子に依存します。次のように使用します。

SIGN_EXTEND(0x89abcd, 23, int32_t);

あなたの問題のために、あなたは使用することができます:

long int hex2li (char string[])
{
    char *pEnd;
    long int result = SIGN_EXTEND(strtol (string, &pEnd, 16), 23, long int);

    if(pEnd[0] == '\0')
        return result;
    return LONG_MIN;
}
于 2010-05-06T14:43:27.157 に答える
1

基数 16 で strtol を使用できない理由はありますか?

于 2010-05-06T15:20:52.887 に答える
0
  if (toupper (string[0]) == 'F')
  {
     return (result | 0xFF000000);
  }

これにより、正しい符号の数値が生成されます。

  if (toupper (string[0]) == 'F')
  {
     return ( ~(result | 0xFF000000) + 1);
  }

これは常に肯定的な結果を生み出します

于 2010-05-06T14:40:32.437 に答える