2011-10-17 25 views
5

は:構造体のメンバメモリレイアウト

struct S { 
    ANY_TYPE a; 
    ANY_TYPE b; 
    ANY_TYPE c; 
} s; 

を無事以下の仮定は、常にすべてのプラットフォームで真であると想定することはできますか?

((char *)&s.a) < ((char *)&s.c) 
((char *)&s.a + sizeof(s.a) + sizeof(s.b)) <= ((char *)&s.c) 

C++でも?

+0

@VJo:どうやって説明できますか? –

+0

ANY_TYPEの例は何ですか? –

+0

なぜあなたはしたいですか?構造のポイントは、この種のジャグリングをやめることです。 – Beta

答えて

3

はい、少なくともCです。コンパイラは構造体メンバの後ろに自由にパディングを挿入できますが、メンバの順序を変更しないでください。

最初のメンバーの前にパディングを挿入する必要もありません。 C99、6.7.2.1から

:ビットフィールドは、それらの順序で増加アドレスを持って存在する構造物、非ビットフィールドメンバーとユニット内

13/宣言されている。適切に変換された構造体オブジェクトへのポインタは、その最初のメンバ(またはそのメンバがビットフィールドの場合はそれが存在するユニット)を指し、逆の場合も同様です。構造体オブジェクト内に無名のパディングがあるかもしれませんが、最初はありません。

15/構造体または共用体の最後に名前のないパディングがある可能性があります。

+0

Re *これは最初のメンバの前にパディングを挿入してはいけません。*:これはほとんどのコンパイラが非対応であることを意味します。最初のメンバーの前にvtableを追加することは、多態性を実装する非常に一般的なアプローチです。 –

+5

@DavidHammen第1に、vtablesはCではなくC++の実装の詳細です。第2に、第1のメンバーの前のパディングなしの要件は、POD(Plain Old Data)のみです。 vtableを持つクラスはPODではないため、a.oを持つことができます。第1のデータメンバの前にvtableポインタ。 – Sjoerd

1

C++では、これらの前提が確実に成り立つことがあります。このような構造体では、コンパイラはメンバの順序を変更できません。

0

はい、デフォルトでは、C++コンパイラは両方のステートメントを自明にする構造体の要素を移動することはできません。

0
  1. はい( - Can sizeof return 0 (zero)を見る限りはsizeof(ANY_TYPE)がない0であるようにいくつかのコンパイラは非標準であり、それを可能にします)。あなたは< =で安全であるか、標準のコンパイラを想定しています。あまりに

  2. はい

そしてC++インチ

ポインタの比較は、配列と構造体/クラスの内部でのみ意味があり、一般的ではありません。

4

これは構造体に当てはまりますが、アクセス指定子を導入するとすぐにC++で変更されます。コンパイラは、アクセス指定子で区切られたブロック全体を並べ替えることができます。

+0

これは本当ですか?標準では、メンバ変数はクラスにリストされている順序で初期化されています。私は彼らの相対的な順序がそれのおかげで変更することはできないと仮定しています。 – Xeo

+2

@Xeoここを参照してください(例)http://stackoverflow.com/questions/4883655/access-specifier-in-c/4883764#4883764残念ながら、この回答には標準引用符はありません。私はいくつかを提供しようとします。初期化について:初期化はメモリの順序付けとは独立しています。 – pmr