13

string16 進数を表す8 文字があり、それをint. この変換では、文字列"80000000"以上のビット パターンを保持する必要があります。つまり、これらの数値は負になるはずです。残念ながら、素朴な解決策:

int hex_str_to_int(const string hexStr)
{    
    stringstream strm;
    strm << hex << hexStr;
    unsigned int val = 0;
    strm >> val;
    return static_cast<int>(val);
}

私のコンパイラでは動作しませんval > MAX_INT(戻り値が 0 の場合)。val のタイプを に変更してintも、大きい数値は 0 になります。SO に関するさまざまな回答からいくつかの異なるソリューションを試しましたが、まだ成功していません。

私が知っていることは次のとおりです。

  • OpenVMS で HP の C++ コンパイラを使用しています (Itanium プロセッサを使用していると思います)。
  • sizeof(int)私のコードが実行されるすべてのアーキテクチャで少なくとも 4 になります。
  • 数値 > INT_MAX から int へのキャストは実装定義です。私のマシンでは、通常は 0 になりますが、興味深いことに、値が大きすぎる場合にfromlongをキャストするとint結果が返されます。INT_MAX

これを正しく行うのは驚くほど難しいか、少なくとも私にとってはそうでした。これに対するポータブルなソリューションを知っている人はいますか?

アップデート:

に変更static_castするreinterpret_castと、コンパイラ エラーが発生します。上記のコードでC スタイルのキャストを試すように促されたコメントreturn (int)valで、うまくいきました。 このマシンで。 それは他のアーキテクチャでも安全ですか?

4

6 に答える 6

14

C++03 標準の引用、§4.7/3 (整数変換):

宛先の型が符号付きの場合、宛先の型 (およびビット フィールド幅) で表現できる場合、値は変更されません。それ以外の場合、値は実装定義です。

結果は実装定義であるため、定義上、真に移植可能なソリューションは存在しません。

于 2011-09-29T18:50:52.423 に答える
8

キャストと変換を使用してこれを行う方法はありますが、ほとんどは、一部のマシンや一部のコンパイラで明確に定義された動作を持つ未定義の動作に依存しています。未定義の動作に依存する代わりに、データをコピーします。

int signed_val;
std::memcpy (&signed_val, &val, sizeof(int));
return signed_val;
于 2011-09-29T18:52:41.647 に答える
5

符号なしの 2 の補数は、補数を取って 1 を足すことで否定できます。それでは、ネガに対してそれを行いましょう:

if (val < 0x80000000) // positive values need no conversion
  return val;
if (val == 0x80000000) // Complement-and-addition will overflow, so special case this
  return -0x80000000; // aka INT_MIN
else
  return -(int)(~val + 1);

これは、int が 32 ビットの 2 の補数表現で表されている (または同様の範囲を持っている) ことを前提としています。符号付き整数オーバーフローに関連する未定義の動作には依存しません (符号なし整数オーバーフローの動作は明確に定義されていることに注意してください - ただし、ここでも発生しないはずです!)。

int が 32 ビットでない場合、事態はさらに複雑になることに注意してください。~(~0U >> 1)の代わりに次のようなものを使用する必要がある場合があります0x80000000。さらに、int が 2 の補数でない場合、特定の値でオーバーフローの問題が発生する可能性があります (たとえば、1 の補数のマシンで-0x80000000は、32 ビットの符号付き整数で表すことができません)。ただし、今日では非 2 の補数のマシンは非常にまれであるため、これが問題になることはほとんどありません。

于 2011-09-29T18:30:39.983 に答える
4

Here's another solution that worked for me:

if (val <= INT_MAX) {
    return static_cast<int>(val);
}
else {
    int ret = static_cast<int>(val & ~INT_MIN);
    return ret | INT_MIN;
}

If I mask off the high bit, I avoid overflow when casting. I can then OR it back safely.

于 2011-09-29T18:55:23.520 に答える