web-dev-qa-db-ja.com

符号付き整数と符号なし整数の間のキャストは、メモリ内の変数の正確なビットパターンを維持しますか?

ソケットを介して32ビットの符号付き整数xを渡したいです。受信者がどのバイトオーダーを期待するかを知るために、送信する前にhtonl(x)を呼び出しています。 htonluint32_tを期待していますが、int32_tuint32_tにキャストするとどうなるかを確認したいと思います。

int32_t x = something;
uint32_t u = (uint32_t) x;

xuのバイトがそれぞれ完全に同じになるのは常に問題ですか?キャストバックについてはどうですか:

uint32_t u = something;
int32_t x = (int32_t) u;

負の値は大きな符号なしの値にキャストされますが、反対側にキャストするだけなので問題ではありません。ただし、キャストが実際のバイトを混乱させる場合、キャストバックが同じ値を返すことを確信できません。

27
Flash

一般に、Cでのキャストはビットパターンではなく値で指定されます-前者は(可能であれば)保存されますが、後者は必ずしもそうではありません。パディングなしの2の補数表現の場合(これは、固定整数型に必須です)、この区別は重要ではなく、キャストは実際には何もしません。

ただし、符号付きから符号なしへの変換がビットパターンを変更したとしても、再度変換すると元の値が復元されます-範囲外の符号なしから符号付きへの変換は実装定義であり、信号を発生させる可能性があることに注意してくださいオーバーフロー。

完全な移植性(おそらくはやり過ぎ)を実現するには、変換の代わりに型の破棄を使用する必要があります。これは、次の2つの方法のいずれかで実行できます。

ポインタキャスト経由、すなわち

uint32_t u = *(uint32_t*)&x;

有効な型付け規則に違反する可能性があるので注意が必要です(ただし、整数型の符号付き/符号なしのバリアントには問題ありません)。

uint32_t u = ((union { int32_t i; uint32_t u; }){ .i = x }).u;

また、たとえばdoubleからuint64_tへの変換にも使用できます。未定義の動作を回避する場合は、ポインターキャストを使用しないでください。

26
Christoph

Cでは、キャストは「型変換」と「型の曖昧性解消」の両方を意味するために使用されます。次のようなものがある場合

_(float) 3
_

その後、それは型変換であり、実際のビットが変更されます。あなたが言うなら

_(float) 3.0
_

それは型の曖昧性解消です。

2の補数表現を想定(以下のコメントを参照)、intを_unsigned int_にキャストすると、ビットパターンは変更されず、意味的な意味のみが変更されます。キャストバックすると、結果は常に正しいものになります。ビットが変更されず、コンピューターがそれらを解釈する方法のみが変更されるため、型の曖昧性解消の場合に該当します。

理論的には、2の補数は使用できません。また、unsignedsignedは非常に異なる表現を持つ可能性があり、その場合、実際のビットパターンは変わる可能性があります。

ただし、C11(現在のC標準)から、実際にsizeof(int) == sizeof(unsigned int)が保証されます。

(§6.2.5/ 6)符号付き整数型のそれぞれに、同じ量のストレージ(符号情報を含む)を使用し、同じ値を持つ対応する(ただし異なる)符号なし整数型(キーワードunsignedで指定)がありますアライメント要件[...]

実際には、あなたはそれが安全であると仮定することができます。

6

intXX_t型は2の補数になることが保証されているため、これは常に安全でなければなりませんif

7.20.1.1正確な幅の整数型typedef名intN_tは、幅N、パディングビットなし、2の補数表現を持つ符号付き整数型を指定します。したがって、int8_tは、正確に8ビットの幅を持つ符号付き整数型を示します。

理論的には、uint32_tからint32_tへの逆変換は、すべてのunsignedからsignedへの変換と同様に、実装定義です。しかし、プラットフォームがあなたが期待するものとは異なる動作をすることはあまり想像できません。

これを本当に確認したい場合は、手動でその変換を行うことができます。 > INT32_MAXの値をテストしてから、少し計算するだけです。それを体系的に行ったとしても、まともなコンパイラーはそれを検出して最適化できるはずです。

2
Jens Gustedt