char *変換とエイリアシングの規則

厳密なエイリアシング規則に従う:

struct B { virtual ~B() {} };
struct D : public B { };

D d;
char *c = reinterpret_cast(&d);

A char* to any object of different type is valid. But now the question is, will it point to the same address of &d? what is the guarantee made by C++ Standard that it will return the same address?

5
@Oli:構造体をファイルに書き込むとか、同じアドレスを指していないと変換がどのように成功するのでしょうか?例えば。上記の例の struct D にメンバー int x; があった場合、 char * はxの最初のバイトを指していることが保証されていますか?
追加された 著者 user1086635,
良い質問。キャストによっては、実際にアドレスを変更することができます(複数の継承が関係する場合など)。そうだと思います。
追加された 著者 Kos,
「同じ住所」とはどういう意味ですか?何が何に等しいべきですか?
追加された 著者 n.m.,
あなたのデストラクタが間違っていると思う
追加された 著者 Seth Carnegie,
私は答えを知らない。しかし、この知識はいつ実践上有用か
追加された 著者 Oliver Charlesworth,
@ user1086635:あなたは本当に非 POD データ型をシリアライズしたくないそれらをバイト列として再解釈します。たとえば、あなたのケースでは、その仮想関数は、クラスインスタンスが vptrs を持つことを意味します。これを逆シリアル化できる便利な方法はありません。
追加された 著者 Oliver Charlesworth,
どこに質問がありますか? (あなたが解決できない問題)
追加された 著者 Qchmqs,

3 答え

c and &d do indeed have the same value, and if you reinterpret-cast c back to a D* you get a valid pointer that you may dereference. Furthermore, you can treat c as (pointer to the first element of) an opaque array char[sizeof(D)] -- this is indeed the main purpose of casting pointers to char pointers: To allow (de)serialization (e.g. ofile.write(c, sizeof(D));), although you should generally only do this for primitive types (and arrays thereof), since the binary layout of of compound types is not generally specified in a portable fashion.

@Oliは正しいことを指摘して強調したいので、複合型を全体としては決して直列化しないでください。多態性クラスの実装とデータフィールド間のパディングは指定されておらず、アクセスできないため、ほとんどの場合、結果は直列化解除できません。

Note that reinterpret_cast(static_cast(&d)) may be treated as an opaque array char[sizeof(B)] by similar reasoning.

6
追加された
@OliCharlesworth:Hm、オブジェクトには、隠された "vptrs"がありません。これはクラス実装のすべてです。仮想継承に入るまでは、オブジェクトはかなり "普通"のレイアウトになっているはずです...通常のパディングの問題は、クラスのタイプを「素朴な」方法で並べ替えないようにする直接的な理由です(ただし、それが問題ない状況、例えば、メモリマップされたネットワークI/Oを使用する同一のマシンのHPCクラスタ...)。バイヤーは注意してください:-)
追加された 著者 Kerrek SB,
@OliCharlesworth:うーん、私はこれについて間違った考えを持っているかもしれない...私はいつもクラスあたり1つのvtableしかないと思った。必要なのは、メンバー関数を呼び出すためのインスタンスポインタです。
追加された 著者 Kerrek SB,
@OliCharlesworth:同じマシンのコレクションに同じ実行ファイルをデプロイしても、これらのvptrは修正されません。
追加された 著者 Kerrek SB,
おそらく、このような非PODクラス(つまり、vptrsを持つクラス)をシリアライズ/デシリアライズすることは非常に悪い考えです。
追加された 著者 Oliver Charlesworth,
何?仮想関数の存在は、クラスインスタンスがvptrを持たなければならないことを意味します(通常の実装では)。
追加された 著者 Oliver Charlesworth,
実際、クラスにはvtableが含まれています。しかし、各インスタンスには、vtableをポイントするvptrが含まれています。
追加された 著者 Oliver Charlesworth,
多分そうでないかもしれません;実装定義/未定義の動作の領域にあることは間違いありません。 ASLRやリロケータブルオブジェクトのようなものは間違いなく物事を台無しにするでしょう。
追加された 著者 Oliver Charlesworth,

セクション5.2.10、2003年のC ++標準の第7ポイントは次のように述べています。

オブジェクトへのポインタは、オブジェクトへのポインタに明示的に変換できます。   異なるタイプのオブジェクト。タイプの右辺値を変換することを除いて   "T1へのポインタ"を "T2へのポインタ"型に変換します(ここで、T1とT2は   オブジェクトタイプ、およびT2のアラインメント要件がnoの場合   T1よりも厳しい)、元のタイプに戻ると   元のポインタ値の場合、そのようなポインタ変換の結果は次のようになります。   不特定。

「同じアドレス」で「元のポインタ値」を意味する場合は、このエントリに「はい」と表示されます。

2
追加された

その意図ははっきりしており(議論する必要のあるものではない)

reinterpret_cast never changes the value of an address, unless the target type cannot represent all address values (like a small integer type, on a pointer type with intrinsic alignment: f.ex. a pointer that can only represent even addresses, or pointers to object and pointers to functions cannot be mixed...).

標準の言葉ではそれを捕らえることはできませんが、実際には実際の問題があるわけではありません。

char *c = reinterpret_cast(&d);

c will point to the first byte of d, always.

0
追加された