どこにC++仕様がありますか?かっこいいね。私はこれがどのように仕様化されているか知りたい。私は、未定義型へのポインタを持つことが許されている仕様であることに気づいていませんでした。C++標準では未定義の型へのポインタはどこにありますか?
class T;
int main(int argc, char* argv[])
{
int x;
T* p = reinterpret_cast<T*>(&x);
return 0;
}
どこにC++仕様がありますか?かっこいいね。私はこれがどのように仕様化されているか知りたい。私は、未定義型へのポインタを持つことが許されている仕様であることに気づいていませんでした。C++標準では未定義の型へのポインタはどこにありますか?
class T;
int main(int argc, char* argv[])
{
int x;
T* p = reinterpret_cast<T*>(&x);
return 0;
}
あなたがをやっていることは法的こと、それはclass T
の実際の定義に依存するため、我々はあなたが示したコードに基づいて確実に知ることができないことがあります。 C++ 11§3.9.2/ 3以降
:彼らと何ができるかに制限があるが、不完全型への
ポインタが許可されています。
これらの制限事項は、§3に記載されています。2/4:
場合種類
T
が完了しなければならないクラス:
- タイプ
T
のオブジェクトが定義され、又は- タイプ
T
の非静的クラスのデータメンバが宣言され、またはT
はLVA 新しい発現、又は- のオブジェクトタイプまたは配列要素のタイプとして使用されますLUEは対右辺値変換タイプ
T
のオブジェクトを参照glvalueに適用される、または- 発現は
T
、又は- ヌルポインタ定数ではない式を入力する(暗黙的または明示的に)変換されます。 、および暗黙的な変換を使用して
T
にT
または参照に型ポインタに変換され、void*
以外の型であり、クラスメンバアクセス演算子がタイプT
の式に適用されるdynamic_cast
又はstatic_cast
、又は- 、又は
- 戻り型または型
typeid
オペレータ又はsizeof
オペレータは、タイプT
のオペランドに適用される、またはT
の引数の型を持つ関数を定義または呼ばれ- 、又は
- タイプのベース・クラスとクラス
T
であるれます定義された、または- タイプ
T
の左辺値は、Tを有する例外宣言に割り当てられた、又は- タイプ
T
はalignof
式の主題である、又は- れます
T
、T
への参照、またはT
へのポインタ。
我々はポインタ型の間reinterpret_cast
がstatic_cast
の用語で定義されていることを§5.2.10/ 7に見ることができるように第六弾丸は、ここに適切に表示されます。
オブジェクトポインタ明示的に別の型のオブジェクトポインタに変換することができます。タイプのprvalue
v
「T1
へのポインタを」タイプ「CVT2
へのポインタ」に変換されるときT1
とT2
両方が標準レイアウトタイプであり、T2
の位置合わせ要件がT1
のものよりも厳しくない場合、結果はstatic_cast<cv T2*>(static_cast<cv void*>(v))
ありますいずれかのタイプがvoid
の場合「T1
へのポインタ」タイプのPR値をタイプ「T2
へのポインタ」(T1
およびT2
がオブジェクトタイプであり、のアラインメント要件がT1
よりも厳しくない)に変換し、元のタイプに戻すと、ポインタ値。そのような他のポインタ変換の結果は不特定である。
しかし、第六弾が適用されないことを、最初void*
へreinterpret_cast
static_cast
のため、実際の結果のポインタ型へ、その後。
T
が不完全なタイプであるにもかかわらず、これまでのところ法的領域にあります。しかし、T
が標準レイアウトタイプではないか、またはint
よりも厳密な位置合わせ要件を持っていると判明した場合、5.2.10/7の最後の文が真であり、あなたはUBを呼び出しています。
あなたのケースについては、セクション5.2.10(7)(ISO/IEC14882のように:1998(E)と同様に、2011 FDISで)。
無関係な型(char*
以外)へのポインタをキャストした後で許可されているのは、元のポインタ型にキャストされます。
@cli_hltはセクションを提供することに私を打ち負かしました。
ここでルールそのものです:
オブジェクトポインタが明示的に異なるタイプのオブジェクトポインタに変換することができます。 タイプのprvalue
v
「T1
へのポインタを」タイプ「cv
T2
へのポインタ」に変換される場合T1
とT2
両方が標準レイアウトタイプ(3.9)であり、T2
の位置合わせ要件がある場合、結果はstatic_cast<cv T2*>(static_cast<cv void*>(v))
ありますT1
よりも厳密でないか、いずれかのタイプがvoid
の場合。型に型 のprvalue「T1
へのポインタを」変換「T2
へのポインタ」(T1
とT2
がオブジェクト型であり、ここでT2
の位置合わせ要件がT1
のものよりも厳しくない場合)と元の形にすると、得られます元のポインタ値。そのような他のポインタ変換の結果は不特定である。
厳密なエイリアシング規則は無関係タイプを介してオブジェクトへのアクセスを禁止します。 https://stackoverflow.com/a/7005988/103167
あなたの質問に幾分関連するもう一つのルールはセクション5.4で発見された参照してください:
キャスト表記を使用して、キャストのオペランドがタイプ「不完全なクラス型へのポインタ」のprvalueすることができます。 キャスト表記を使用するキャストの宛先タイプは「不完全なクラスタイプへのポインタ」になる可能性がありますオペランドタイプと宛先タイプの両方がクラスタイプで、どちらかまたは両方が不完全な場合は、
static_cast
またはreinterpret_cast
解釈が使用されているかどうかは不明ですたとえ2つのクラスの間に継承関係 があっても
私はあなたが許可されていると考えているか分かりません。 1つのポインタタイプから十分に大きな他のポインタタイプへのreinterpret_cast
の可能性があり、再び元のタイプに戻って元のポインタになるという保証があります。この仕様は5.2.10 [expr.reinterpret.cast]にあります。それは、次のように動作することが保証されている:
T* ptr = ...;
S* sptr = reinterpret_cast<S*>(ptr);
T* tptr = reinterpret_cast<T*>(sptr);
assert(ptr == tptr);
私たちは、このトピックに今週初めセッションの議論のうちを持っていた:死ステーション9000の実装ならばCの適合実装されるであろう(++もしようとしますプログラムの実行開始時にランダムに選択されたビットパターンでポインタのビットパターンをXORすると、reinterpret_cast<T>(x)
に含まれる型がchar
に含まれていない場合、これは許容される実装になります。コンセンサスはこれがOKであろうということでした。
私は今、私の質問が分かりません。私は、未定義型へのポインタを持つことが許されている仕様であることに気づいていませんでした。 – Mike
また、私の 'reinterpret_cast <>()'が間違った型を使用していることに気付きました!私はこれを2番目に修正します(混乱を招いて申し訳ありません)。「S」と「T」は2つのレイアウト互換型であり、キャストで使用されることを意図しています。 –
これはどのように許可されていますか?なぜなら、 'reinterpret_cast'は実装定義の動作か*未定義の動作です*。いずれにせよ、それは仕様によって定義されていないので、「許可」とみなせるかどうかはわかりません。それとも、前方宣言だけについて話していますか? –
なぜこれはクールだろうか? – Bart
@Bartあなたは厄介なことをすることができるので、多分? – tibur