それは目的ではないからreinterpret_cast
です。reinterpret_cast
整数型または列挙型がそれ自体である可能性があることを除いて、許可されているすべての変換には、ポインターまたは参照が含まreinterpret_cast
れます。これはすべて標準で定義されています[expr.reinterpret.cast]
。
ここで何を達成しようとしているのかはわかりませんrandomIntNumber
が、と同じ値にしたい場合randomUintNumber
は、
const int64_t randomIntNumber = randomUintNumber;
その結果、コンパイラの警告が発生する場合、またはより明示的にしたい場合は、次のようにします。
const int64_t randomIntNumber = static_cast<int64_t>(randomUintNumber);
が263randomUintNumber
未満の場合、キャストの結果は入力と同じ値になります。それ以外の場合、結果は実装定義ですが、それを定義するすべての既知の実装は、明らかなことを実行することを期待しています。結果は、 264を法とする入力と同等です。int64_t
randomIntNumber
と同じビットパターンが必要な場合は、次のrandomUintNumber
ように実行できます。
int64_t tmp;
std::memcpy(&tmp, &randomUintNumber, sizeof(tmp));
const int64_t randomIntNumber = tmp;
2の補数int64_t
表現を使用することが保証されているため、範囲外の値に対して実装がこれと同じ結果になるように定義することをお勧めします。ただし、標準のAFAIKでは実際には保証されていません。static_cast
uint64_t
がコンパイル時定数であってもrandomUintNumber
、残念ながらここでrandomIntNumber
はコンパイル時定数ではありません。では、コンパイル時定数はどの程度「ランダム」なのでしょうか。;-)
それを回避する必要があり、範囲外の符号なしの値を符号付きの型に変換することについて実装が賢明であると信頼できない場合は、次のようになります。
const int64_t randomIntNumber =
randomUintNumber <= INT64_MAX ?
(int64_t) randomUintNumber :
(int64_t) (randomUintNumber - INT64_MAX - 1) + INT64_MIN;
今、私は可能な限り真にポータブルなコードを書くことに賛成ですが、それでもこれはパラノイアの危機に瀕していると思います。
ところで、あなたはこれを書きたくなるかもしれません:
const int64_t randomIntNumber = reinterpret_cast<int64_t&>(randomUintNumber);
または同等に:
const int64_t randomIntNumber = *reinterpret_cast<int64_t*>(&randomUintNumber);
int64_t
これらが存在しuint64_t
、同じサイズの符号付き型と符号なし型であることが保証されている場合でも、実際には標準整数型の符号付きバージョンと符号なしバージョンであることが保証されていないため、これが機能することは完全には保証されません。したがって、このコードが厳密なエイリアシングに違反しているかどうかは、実装固有です。厳密なエイリアシングに違反するコードの動作は未定義です。以下は厳密なエイリアシングに違反しておらずrandomUintNumber
、のビットパターンが次の値の有効な表現である場合は問題ありませんlong long
。
unsigned long long x = 0;
const long long y = reinterpret_cast<long long &>(x);
したがって、とがandのtypedefである実装ではint64_t
、uint64_t
myはOKです。また、範囲外の値から符号付き型への実装定義の変換と同様に、実装で行うのが賢明なことは、それらを対応する符号付き/符号なし型にすることであると予想されます。したがって、および暗黙の変換と同様に、適切な実装で機能することを期待しますが、実際には保証されません。long long
unsigned long long
reinterpret_cast
static_cast