coutとprintfから関数のパラメータ伝達過程の検討

2750 ワード

coutとprintfから関数のパラメータ伝達過程の検討
コードを見てみましょう
#include
int i=0;
int update(){i++;return i;}
int main()
{
	printf("update():%d i:%d
",update(),i); return 0; }

出力結果は何だと思いますかupdate():1 i:1?間違っています.正しい出力はupdate():1 i:0です.
なぜそうなるのか、まず実験康をしましょう.
#include
#include 
#include 
using namespace std;
int i=0;
int update(){i++;return i;};
int main()
{
	printf("----------------------------test printf----------------------------
"); printf("before:%d
",i); printf("update():%d i:%d
",update(),i); printf("later:%d
",i); printf("before:%d
",i); printf("i:%d update():%d
",i,update()); printf("later:%d
",i); printf("update1:%d update2:%d update3:%d",update(),update(),update()); }

その出力結果は
----------------------------test printf----------------------------
before:0
update():1 i:0
later:1
before:1
i:2 update():2
later:2
update1:5 update2:4 update3:3

printfだけがそうですか?いいえ、可変パラメータの印刷関数にはこのような特性があります.coutをテストして検証してみましょう.
#include
#include 
#include 
using namespace std;
int i=0;
int update(){i++;return i;};
int main()
{

	cout<

出力結果は次のとおりです.
---------------------------- test cout ----------------------------
before:0
update():1 i:0
later:1
before:1
i:2 update():2
later:2
update1:5 update2:4 update3:3


なぜそうなるのか、cとc++の関数パラメータに関するプロセスを話さなければなりません.
アセンブリ内の関数パラメータは、最後のパラメータから最初のパラメータまでそれぞれスタックに入力されます.このように、関数がパラメータを取るとき、popが出る順序は1-nです.
したがって、printf("update():%d i:%d
",update(),i);
では、関数はiを先に圧入し、update()を実行し、その戻り値をスタックに圧入する.
以上は理論にすぎず,実際の環境ではx 86,x 64,32ビット,16ビットマシンによって,それらの具体的なパラメータ伝達方式はやや異なる:)
x 64の次の文のアセンブリコードを見てみましょう
mov     ebx, cs:i
call    _Z6updatev      ; update(void)
mov     r8d, ebx
mov     edx, eax
lea     rcx, aUpdateDID ; "update():%d i:%d
" call _ZL6printfPKcz ; printf(char const*,...)

X 64の下では、レジスタパラメータである.最初の4つのパラメータはそれぞれrcx rdx r 8 r 9でパラメータを伝達する.余計なスタックを通って参を伝える.右から左へスタックに入ります.
上記のコードではフォーマット文字列がrcx(最後の付与)にあり、update()はedx、2番目の付与値を返します.i r 8における最初の付与.
しかし、mov ebx, cs:iプログラムは、iの値をebxに移動し、update関数を呼び出し、戻り値のあるレジスタeaxをedxに移動するのを見ることができます.
プロシージャは少し変化しますが、最後の結果は、アセンブリ内の関数パラメータと最後のパラメータから最初のパラメータにそれぞれスタックされます.
最後のお題ですね//
#include 
int main()
{
    long long a = 1, b = 2, c = 3;
    printf("%d %d %d
", a,b,c); return 0; }

しゅつりょくを求める
答えと解析