コンパイラは、これらのステートメントの両方に対して同じコードを生成しますか?
foo1(int* val){(*val)++;}
foo2(int &val){val++;}
単純に foo のスタック フレームのパラメータ部分にポインタを書き込むのでしょうか? または、2 番目のケースでは、呼び出し元と foos のスタック フレームがオーバーラップして、呼び出し元のローカル変数がスタック上で foo のパラメーターと同じメモリを使用するようになりますか?
コンパイラは、これらのステートメントの両方に対して同じコードを生成しますか?
foo1(int* val){(*val)++;}
foo2(int &val){val++;}
単純に foo のスタック フレームのパラメータ部分にポインタを書き込むのでしょうか? または、2 番目のケースでは、呼び出し元と foos のスタック フレームがオーバーラップして、呼び出し元のローカル変数がスタック上で foo のパラメーターと同じメモリを使用するようになりますか?
これらの 2 つの呼び出しは、奇妙なコンパイラを使用していない限り、まったく同じコードを生成するはずです。
場合によります。
ライブラリにコンパイルされた場合、ほとんどのプラットフォームで同一ではないにしても、両方に対して生成されたコードは同等になります。
優れたコンパイラはこのような小さな関数をインライン化するため、スタック上の何かのアドレスを取得してポイントされた値をインクリメントするのではなく、値を直接インクリメントする可能性があります。インライン関数のスタックフレームは呼び出し元のスタックフレームに埋め込まれているため、その場合は重複します。
スタックをオーバーラップさせることはできません。
引数がグローバル、ヒープオブジェクトである可能性があること、またはスタックに格納されている場合でも、最後の要素ではない可能性があることを考慮してください。呼び出し規約によっては、他の要素が1つのスタックフレームと関数に渡されるパラメーター(つまり、差出人住所)の間に配置される場合があります。
また、スタックに何も追加されていなくても、関数のコンパイル中に決定を下すことはできず、コンパイラーが呼び出し元の関数を処理しているときに決定を下すことができることに注意してください。関数がコンパイルされると、それがどこから呼び出されたかによって変更されることはありません。