2016-12-23 21 views
3

reinterpret_castはこれには安全ですか?これを行う最良の方法はありますか?符号なし整数にC++で符号なし整数を書き込む

たとえば、以下のコードではibytestreamというクラスがあり、それによってuint16_tおよびint16_tが読み取られます。 ibytestream::nextvector<unsigned char>::iteratorです。

inline ibytestream& operator>>(ibytestream& stream, uint16_t& data) { 
    data = 0; 
    data |= *stream.next++; 
    data <<= 8; 
    data |= *stream.next++; 
    return stream; 
} 

inline ibytestream& operator>>(ibytestream& stream, int16_t& data) { 
    return stream >> reinterpret_cast<uint16_t&>(data); 
} 

Iは、整数のバイトを変換するためのコードを複製したくないので、私は、符号なしのバージョンからコードを再利用するために署名されたバージョンのreinterpret_castを用います。私のマシンでは正常に動作しますが、他の現代マシンでは一般的に動作しますか?

+0

厳密なエイリアシングルールに違反しないでしょうか? http://stackoverflow.com/q/98650/417197 –

+1

@Andreルールは、整数型と符号付き/符号なしバリアントの間のエイリアシングを許可します –

答えて

3

はい、これは安全です。標準の

3つの部分がこの決意するために適用されますの

  1. アライメント要件を符号付きおよび符号なしのタイプは同じ
  2. ポインターが許可されている同一のアライメント要件タイプへのポインタとの間にキャストされ
  3. 場合glvalues間のキャストが実行され、対応するポインタ間のキャストが有効な場合、キャストは有効です。標準の符号付き整数型のそれぞれについて

、対応する(しかし異なる)標準の符号なし整数型が存在する:unsigned charunsigned short intunsigned intunsigned long int、 とunsigned long long int、同じ量を占める各々が同一の位置合わせ要件を有する。

オブジェクトポインタは、明示的に異なるタイプのオブジェクトポインタに変換できます。タイプ "ポインタのT1"のタイプをポインタ "T2へのポインタ"(ここで、T1とT2はオブジェクトタイプであり、T2のアライメント要件はT1のアライメント要件よりも厳しくない)に変換し、元のタイプに戻すと元のポインタ値。

reinterpret_castを使用して、 "T1へのポインタ"型の式を "T2へのポインタ"型に明示的に変換できる場合、タイプT1のglvalue式を "T2への参照"型にキャストできます。結果は、 をソースのglvalueと同じオブジェクトに指定しますが、指定したタイプを使用します。

+0

私は彼のコメントにM.Mが言及している部分が欠けていると思います。対応する符号なしタイプの式を使用して符号付き整数オブジェクトにアクセスできることを示します。 – MSalters

1

はい、これは問題ありません。 (潜在的なエンディアンの問題を抱えているが、それは両方の符号付きと符号なしの番号に適用され、別の問題ですint型とバイト配列との間で移動する。)完全に異なる

何か:このビット:

data = 0; 
data |= *stream.next++; 

を...することができます簡略化する:

data = *stream.next++; 
+0

私のコードにはエンディアンの問題はないと思います。基礎となるマシンのエンディアンに関係なく、バイトは常にビッグエンディアンで読み込まれます。また、コードが一貫して見えるように単純化しませんでした(つまり、 'data | = * stream。次の++;複数の行にわたって繰り返されます)、私はコンパイラがそれを最適化するのに十分スマートであると想定します。 – Bernard

+0

アーキテクチャ間で移植性が必要な場合にのみ問題になります。それは必要ないと思われます。すべての良い。 –

関連する問題