誰かがここで何が起こっているのか詳しく説明してください。
int main()
{
int **p = 0;
//p=? and why| *p=? and why|**p=? and why
++p;
//p=? and why| *p=? and why|**p=? and why
printf("%d\n", p);
return 1;
}
出力:-
- 4(なぜ?)
誰かがここで何が起こっているのか詳しく説明してください。
int main()
{
int **p = 0;
//p=? and why| *p=? and why|**p=? and why
++p;
//p=? and why| *p=? and why|**p=? and why
printf("%d\n", p);
return 1;
}
出力:-
まず第一に、p
整数へのポインタへのポインタです。
int **p = 0;
p
= 0、*p
=なし、**p
=なし未満。
++p;
p = p+1と同じです。さらにintへのポインタへの1つのポインタのサイズを意味します。ポインタは基本的に、少なくともOSでは32ビット長(4バイト)です。p
現在、0の後に4バイトを指します。の値p
は4です。
p
へのポインタへのポインタint
です。これはに初期化されてい0
ます。つまり、nullポインタです。
次に、メモリ内の次の連続するポインタを指すようにインクリメントさint
れます。* プラットフォームではポインタのサイズが4バイトであるため、次のポインタはアドレス4になります。
次に、printfはポインタ値を整数として解釈するため、「4」を表示します。
*ただし、これは未定義の動作であることに注意してください。
明らかです。intへのポインタ(intへのポインタへのポインタをint **p
意味します)へのポインタがあり、実際にはアドレス0を保持しています。アーキテクチャでは、ポインタ自体の長さは32ビット(4バイト)であるため、インクリメントp
するとp + 4、つまり0 + 4=4になります。
素敵なCの本を手に入れて、ポインタ演算について学びましょう。あなたはあなたの人生の残りの部分を喜ぶでしょう!:)
++p
は実際には未定義の動作ですが、実装で発生したように見えるのsizeof(int*)
は4であり、nullポインタはアドレス0です。UBでない場合、ポインタの増分により、アドレスに次のサイズに等しいバイト数が追加されることを思い出してください。参照タイプ。したがって、型のnullポインタint**
(したがって、referand型はint*
)を取得してインクリメントすると、アドレスに到達することはそれほど驚くことではありません4
。保証されているわけではありません。
%d
フォーマットがanを予期しているときにポインタを渡すことint
も未定義の動作ですが、との表現にint
はint**
十分な互換性があり、実装のvarargs呼び出し規約はそれらを十分に同様に扱い、正常に出力されたよう4
です。これは、が保証されていない実装にとってもそれほど驚くべきことでsizeof(int) == sizeof(int**)
はありません。
もちろん、これは未定義の動作であるため、表示される内容については他にも考えられる説明があります。
pはintへのポインタへのポインタです。そして、それは0、つまりNULLに初期化されます。
インクリメントすると、intへの次のポインタを指すようになります。これは32ビットシステムではたまたま4です。