1

私は当時、reinterpret_cast<>それをどのように使用すべきかについて多くのことを読んできました(そしてほとんどの場合、それを避けてください)。

reinterpret_cast<>to を使用して from をキャストすることは理解していますが、 unsigned char*tochar*実装で定義されている(したがって非移植性) であり、一方を他方に効率的に変換する方法は他にないようです。

unsigned char*いくつかの計算を処理するために扱うライブラリを使用するとしましょう。内部的には、私はすでにchar*自分のデータを保存するために使用しています(変更すると子犬が殺されるため、変更できません)。

私は次のようなことをしたでしょう:

char* mydata = getMyDataSomewhere();
size_t mydatalen = getMyDataLength();

// We use it here
// processData() takes a unsigned char*
void processData(reinterpret_cast<unsigned char*>(mydata), mydatalen);

// I could have done this:
void processData((unsigned char*)mydata, mydatalen);
// But it would have resulted in a similar call I guess ?

コードの移植性を高めたい場合は、最初にデータをコピーするしかないようです。何かのようなもの:

char* mydata = getMyDataSomewhere();
size_t mydatalen = getMyDataLength();
unsigned char* mydata_copy = new unsigned char[mydatalen];
for (size_t i = 0; i < mydatalen; ++i)
  mydata_copy[i] = static_cast<unsigned char>(mydata[i]);

void processData(mydata_copy, mydatalen);

もちろん、それは非常に最適ではなく、最初のソリューションよりも移植性が高いかどうかさえわかりません。

問題は、移植性の高いコードを作成するには、この状況で何をするかということです。

4

4 に答える 4

6

ポータブルは実際の問題です。そのため、とreinterpret_castの間の変換の特定の使用法は移植可能です。それでも、この使用法を各場所で直接行うのではなく、関数のペアでラップします。char*unsigned char*reinterpret_cast

ほとんどすべての疣贅 ( の限られた保証に関するものを含むreinterpret_cast) が効率性をサポートしている言語を使用する場合、非効率性を導入することに行き過ぎないでください。

それは、文字を守りながら、言語の精神に反することになります。

乾杯 & hth。

于 2011-01-16T22:19:35.443 に答える
2

char 型と unsigned char 型の違いは、単なるデータ セマンティクスです。これは、コンパイラがいずれかのタイプのデータ要素に対して算術演算を実行する方法にのみ影響します。char 型は、コンパイラが 2 の補数演算を実行するように、上位ビットの値が負として解釈されることをコンパイラに通知します。これが 2 つのタイプの唯一の違いであるため、 とはreinterpret_cast <unsigned char*> (mydata)異なる出力を生成するシナリオは想像できません(unsigned char*) mydata。さらに、データのセマティクスの変更、つまり符号付き演算から符号なし演算への切り替えについてコンパイラに通知するだけの場合は、データをコピーする必要はありません。

編集:上記は実用的な観点からは当てはまりますが、C++ 標準では、char、unsigned char、sign char が 3 つの異なるデータ型であると規定されていることに注意してください。§ 3.9.1.1:

文字 (char) として宣言されたオブジェクトは、実装の基本文字セットのメンバーを格納するのに十分な大きさでなければなりません。このセットの文字が文字オブジェクトに格納されている場合、その文字オブジェクトの整数値は、その文字の単一文字リテラル形式の値と等しくなります。char オブジェクトが負の値を保持できるかどうかは実装定義です。文字は、署名なしまたは署名付きで明示的に宣言できます。Plain char、signed char、および unsigned char は 3 つの異なる型であり、まとめてナロー文字型と呼ばれます。char、signed char、および unsigned char は、同じ量のストレージを占有し、同じ配置要件 (3.11) を持ちます。つまり、それらは同じオブジェクト表現を持っています。細字タイプの場合、オブジェクト表現のすべてのビットが値表現に参加します。符号なしのナロー文字型の場合、値表現の可能なすべてのビット パターンは数値を表します。これらの要件は、他のタイプには当てはまりません。特定の実装では、プレーンな char オブジェクトは、signed char または unsigned char と同じ値を取ることができます。どちらが実装定義です。

于 2011-01-17T01:03:01.240 に答える
1

キャストに合わせて、実際には問題ありません。

これを追加したいだけです:

for (size_t i = 0; i < mydatalen; ++i)
  mydata_copy[i] = static_cast<unsigned char>(mydata[i]);

未定義の動作ではありませんが、2 の補数演算を使用しないマシンで文字列の内容を変更する可能性があります。逆は、未定義の動作になります。

于 2011-01-17T01:21:27.097 に答える
1

C との互換性のために、unsigned char*およびchar*型には追加の制限があります。理論的根拠は、関数のようなものが機能memcpy()しなければならないということであり、これによりコンパイラの自由度が制限されます。(unsigned char*) &fooオブジェクト foo を指している必要があります。したがって、この特定のケースでは心配しないでください。

于 2011-01-17T08:21:29.397 に答える