2

つまり、arrという名前のCまたはC++のunsignedchar配列を(unsigned short *)arrとしてキャストし、それに割り当てた場合、結果はマシンのエンディアンとは無関係ですか?

補足-IBMやSOに関する他の場所での議論を例を挙げて見ました。

unsigned char endian[2] = {1, 0};
short x;
x = *(short *) endian;

... xの値はエンディアンのレイアウトに依存し、したがってマシンのエンディアンに依存すると述べています。つまり、配列の間接参照はエンディアンに依存しますが、配列に割り当てるのはどうでしょうか。

*(short*) endian = 1;

エンディアンに関係なく、将来のすべてのショートカット逆参照は1を返すことが保証されますか?


回答を読んだ後、私はいくつかのコンテキストを投稿したいと思いました:

この構造体では

struct pix { 
    unsigned char r; 
    unsigned char g;
    unsigned char b; 
    unsigned char a; 
    unsigned char y[2]; 
 }; 

unsigned chary[2]をunsignedshortyに置き換えても個人差はありませんが、これらの構造体の配列を作成して別の構造体に入れると、コンテナ構造体のサイズが大きくなる傾向があることに気付きました。 「unsignedshort」バージョンなので、大きな配列を作成するつもりなので、スペースのオーバーヘッドを節約するためにunsignedchar[2]を使用しました。理由はわかりませんが、uchar[2]をメモリに配置する方が簡単だと思います。

単一の短い長さの数値を意味するその変数yを使用して大量の計算を行う必要があるため、ucharバイトに個別にアクセスすることを避けるために多くの短い値をキャストしていることに気付きます...醜いバイト固有の数学を回避する方法ですが、エンディアンについて考え、次のようにすべてをキャストした場合でも数学が正しいかどうかを考えました

*(unsigned short*)this->operator()(x0, y0).y = (ySum >> 2) & 0xFFFF;

...これは、2次元配列で4つの隣接する近傍を平均化するプログラムの行ですが、重要なのは、uchar[2]フィールドを単一として処理する必要のあるこれらの操作がたくさんあるということです。ショートであり、エンディアンに依存しないショートの操作方法として、最も軽量な(つまり、アクセスまたは割り当てが必要になるたびにエンディアンベースのif-elseステートメントがない)方法を見つけようとしています。

4

3 に答える 3

3

厳密なポインターのエイリアシングのおかげで、未定義の動作であるため、何でもかまいません。ユニオンで同じことをしても答えがノーの場合、結果はマシンのエンディアンに依存します。

于 2012-05-10T07:24:26.697 に答える
3

の可能な各値にshortは、バイト値のシーケンスである、いわゆる「オブジェクト表現」[*]があります。タイプのオブジェクトshortがその値を保持する場合、オブジェクトのバイトはその値のシーケンスを保持します。

エンディアンは、オブジェクト表現が実装に依存する方法の 1 つにすぎないと考えることができます。最小アドレスのバイトは、値の最上位ビットを保持するか、最下位ビットを保持するか?

うまくいけば、これはあなたの質問に答えます。の有効なオブジェクト表現を short としてメモリに安全に書き込んだ場合1、同じメモリから読み戻すと1、その実装での実際のオブジェクト表現に関係なく、同じ値が再び取得されます。特に、エンディアンに関係なく。しかし、他の人が言うように、未定義の動作を避ける必要があります。

[*] または、エキゾチックなアーキテクチャでは、同じ値に対して複数のオブジェクト表現が存在する可能性があります。

于 2012-05-10T08:45:14.647 に答える
1

はい、将来のすべての逆参照も同様に返さ1れます: as 1is in range of type short、変更されずにメモリに配置され、そこにあると変更されません。

ただし、コード自体は効果的な型付けに違反しています。unsigned char[2]としてan にアクセスすることは違法shortであり、アーキテクチャが非境界整列アクセスをサポートしておらず、特に運が悪い場合は、 a が発生する可能性がSIGBUSあります。

ただし、任意のオブジェクトへの文字単位のアクセスは常に有効であり、コードの移植可能なバージョンは次のようになります。

short value = 1;
unsigned char *bytes = (unsigned char *)&value;

もちろん、どのようvalueにメモリに格納されるかは実装定義のままです。つまり、アーキテクチャについてさらに知識がなければ、次のものが何を出力するかを知ることはできません。

assert(sizeof value == 2); // check for size 2 shorts
printf("%i %i\n", bytes[0], bytes[1]);
于 2012-05-10T08:37:55.357 に答える