私はインタビューでこのコードに出くわしました。
int main()
{
int **p;
p = (int **) new int(7);
cout<<*p;
return 0;
}
*pで実行時エラーが発生することを予期していました。しかし、コードを実行すると、出力「0x7」で正常に実行されました。誰かがこれがどのように機能しているか説明してもらえますか?ありがとう。
いくつかの追加の制約が与えられない限り、適切な答えは上記のどれでもありません。基本的に、コードはを割り当て、そのメモリを(を介して)int
であるかのように解釈します。最初の問題は、であるため、一般的なケースでは結果が指定されておらず、のサイズがのサイズよりも小さい場合(64ビットアーキテクチャを考えてください)、で割り当てられたサイズを超えて読み取っているときに、結果が未定義の動作になることです。電話。int*
reinterpret_cast
reinterpret_cast
int
int*
new
新しいintを作成し、値7で初期化します。
int *x = new int(7);
あなたはそれをポインタ(例えばメモリアドレス7または0x07)にキャストします
int **p = (int**) new int(7);
次に、このアドレスをcoutで表示します。
*p is equal to (int*)7
値が7のポインターです。
int main()
{
int **p; // declare pointer to pointer called p
p = (int **) new int(7); // new allocates integer initialized to value of 7 and returns a pointer. Cast the pointer to a point to pointer. p now represents a pointer to a pointer with contents of 0x7. If you called **p you would get the contents at address 0x7.
cout << *p; // dereference p, this yields a pointer, which is an int of value 0x7.
}
この質問は、ポインタに関する知識をテストすることを目的としている可能性が高いですが、あまり実用的ではないようです。
new int(7);
int
値が であるにメモリを割り当て7
、それへのポインタを返します。
int **p = (int **) new int(7);
そのメモリを として解釈するようにコンパイラに指示しますint**
。
cout << *p;
*p
アドレスがandであることをコンパイラに伝え、int *
その値を出力します。値は0x07
です。(int7
をアドレスとして扱います)。余分な逆参照はクラッシュを引き起こします (正確には未定義の動作です)。
int main()
{
int **p = (int **) new int(7);
cout << *p;
}
したがって、メモリのバイトをnew int(7)
割り当てsizeof(int)
、それへのポインタを返します。メモリがたまたまアドレス X にあるとしましょう。次に、X は にキャストされて(int**)
に格納されp
ます。
*p
これは、 addressの値 7 をとしてint**
解釈することを意味します。int
X
int*
sizeof(int*)
が より大きい場合、sizeof(int)
として読み取ると、 でint*
割り当てられたバッファを超えて読み取られますnew
- データ型や再解釈に関係なく、常に未定義の動作です。
同じサイズの場合、CPU は整数 7 を含むメモリを読み取ろうとします。int*
これは通常、値int*(7)
を生成しますが、標準 5.2.10.5 を調べます。
整数型または列挙型の値は、明示的にポインターに変換できます。値をゼロにするためにヌル ポインターを生成する必要はありません。--- end foonote] 十分なサイズの整数に変換され (そのようなものが実装に存在する場合)、同じポインター型に戻されるポインターは、元の値を持ちます。それ以外の場合、ポインターと整数の間のマッピングは実装定義です。
したがって、整数値は何らかのポインター値に変換されることが保証されていますが、未定義のものはありませんが、値は実装で定義されています。それでも、可逆操作であるため、 7 が値 7を生成する可能性が圧倒的に高くなります。これは、「7」を出力するという観察された動作を説明しています。int
int*
int
、値のスライスを読み取り、それをint
ポインターとして解釈します。エンディアンに応じて、そのスライスは 0 または 7 またはそれ以外のint
値になりますが、表示されるポインタ値に変換できる必要があります。