3

以前、ポインター キャスト中のアライン アクセスに関する質問をここに投稿しました。要約すると、一部のアーキテクチャでは例外がスローされたり、整列アクセスと比較してパフォーマンスが大幅に低下したりする可能性があるため、完全に移植可能にするために非整列アクセスを使用しないことをお勧めします。

ただし、 1 バイト アラインメントを使用したい場合があります。たとえば、ネットワーク データの転送中に、構造内に余分なパディングを追加したくない場合です。したがって、通常、ここで行われることは次のとおりです。

#pragma pack (push, 1)
struct tTelegram
{
   u8 cmd;
   u8 index;
   u16 addr1_16;
   u16 addr2_16;
   u8  length_low;
   u8 data[1];
};
#pragma pack (pop)

次に、私の質問をすでに知っているかもしれません: 構造体に 1 バイト アラインメントを強制すると、構造体メンバーがアラインされていないため、完全に移植できないということですか? パディングなしと移植性の両方が必要な場合はどうすればよいですか?

4

2 に答える 2

3

第 1 に、ミスアライメント メモリ アクセスは、メモリ内の複数のワードにまたがる単一のデータを参照します。たとえば、32 ビット システムではint、アドレス 0、4、8 などの 32 ビットはアラインされますが、1、2、3、5、6、7、9 などではアラインされません。

第 2 に、整列されていないデータは C++ の意味で「例外をスロー」しませんが、CPU レベルで割り込み/トラップ/例外を発生させる可能性があります。たとえば、UNIX の SIGBUS では、通常、これに反応するようにシグナル ハンドラを設定します。ただし、位置合わせされていないデータを移植可能な方法で解析する必要がある場合は、シグナルをキャッチしてそうする必要はありません。ワード境界にまたがるデータをパックおよびアンパックする手順を手動でコーディングします。

構造体では、tTelegramデータは「ずれ」ていませんが、レジスタからパック/アンパックされるときにデータをビットシフトしてマスキングするプロセスは、独立したワードを占めるデータを使用するよりも、より多くのマシンコード命令を必要とする可能性があります。

移植性について - すべての非玩具コンパイラには、説明した方法でパックするオプションがありますが、正確なプラグマは異なります。マルチバイト値のバイトのレイアウトは、ビッグエンディアンまたはリトルエンディアン (または一部の CPU は一部のミスアライン データ アクセスを許可しますが (x86 など)、他の CPU は許可しません (Ultrasparc など)。

于 2012-12-17T00:51:04.247 に答える
2

異なるコンピューター間でデータを転送するときは、常にデータをフォーマットする必要があります。データ形式は読み取り可能である必要はありませんが、バイナリであってもかまいません。バイナリ形式には、各データ項目の正確な位置、そのタイプ、マルチバイト データの場合、バイトが表示される順序、サイズまたはサイズを決定する方法などが含まれます。後で。

別の言い方をすれば、あなたが説明したようなアプローチが使用されているのを見てきましたが、それらが正常であるとは思いませんし、異なるエンティティ間で定義されたフォーマットに関しては、それらは確かに正常ではありません (確かに会社、おそらく異なる部門やグループ間でも) )。私がデータの送受信を行っていた場所では、正確な形式が確実に定義されていました。定義された形式がデータ レイアウトと一致する場合、データのstructデコードにも使用されますが、移植性がないことがわかっており、移植性を意図したコードはこのような機能を使用しようとしません。代わりに、関連するレコードを読み書きし、異なるレコードを適切にデコード/エンコードするものを使用します。多くの場合、デコード/エンコード コードは、正確なデータ レイアウトを記述する何らかのメタ フォーマットから生成されます。

于 2012-12-17T00:12:03.580 に答える