- 締切済み
テスト復習をしているんですが・・・
#include<stdio.h> short Sub1(short *); short Sub2(short *, short); short Sub3(short *); void main(){ short Ans, A, B, C; Ans = A = B = C = 0; Sub1(&A); B = Sub2(&A, A); C += Sub1(&B) + Sub3(&C); Ans = A + B + C; printf("Ans=%d:A=%d:B=%d:C=%d:C=%d\n",Ans, A, B, C); } short Sub1(short *pX){ *pX += 3; return Sub2(pX, 5); } short Sub2(short *pX, short Y){ *pX += Y; return *pX + Y; } short Sub3(short *pX){ *pX += 5; return *pX + 1; } という問題なんですが、 答えはAns=96,A=16,B=32,C=48です。 なぜ、こうなるのかがわかりません。どなたか助けていただけないでしょうか!よろしくお願いします!
- みんなの回答 (3)
- 専門家の回答
みんなの回答
- Oh-Orange
- ベストアンサー率63% (854/1345)
★解説 ・まずは関数について Sub1…引数 pX に 3 を加算します。Sub2 を呼ぶため pX がさらに +5 が加算されます。 戻り値は +5 を加えた pX にさらに +5 した値を返す。 Sub2…引数 pX に Y を加算します。戻り値は Y を加えた pX にさらに +Y した値を返す。 Sub3…引数 pX に 5 を加算します。戻り値は 5 を加えた pX にさらに +1 した値を返す。 ・次は main() 関数です。 (1)short Ans, A, B, C; (2)Ans = A = B = C = 0; (3)Sub1( &A ); (4)B = Sub2( &A, A ); (5)C += Sub1( &B ) + Sub3( &C ); (6)Ans = A + B + C; (7)printf( "Ans=%d:A=%d:B=%d:C=%d:C=%d\n", Ans, A, B, C ); ↓…番号に対応した解説です。 (1)Ans、A、B、C を short 型で宣言しています。 (2)Ans、A、B、C に 0 を代入して初期化しています。 (3)Sub1(0); の実行により、引数 A は A=0 → A += 3 → A += 5 → A=8 となります。 (4)B = Sub2(8,8); の実行により、引数 A は A=8 → A += 8 → A=16 となります。 そして戻り値は A+8 = 16+8 = 24 を返す。よって B=24 となります。 (5)C += Sub1(24) + Sub3(0) の実行により、 ・Sub1(B)…B = 24 → B += 3 → B += 5 → B=32、戻り値は B+5 = 32+5 = 37 を返す。 ・Sub3(C)…C = 0 → C += 5 → C = 5、戻り値は C+1 = 5+1 = 6 を返す。 C += 37 + 6 となりますが、C は既に C=5 ですので C = 5 + 37 + 6 C = 48 (6)(4)より A=16 (5)より B=32 (5)より C=48 よって Ans = A + B + C Ans = 16 + 32 + 48 Ans = 96 (7)Ans=96、A=16、B=32、C=48 を表示しています。 ↑ これによって答えが『Ans=96、A=16、B=32、C=48』になります。 最後に: ・紙に変数 Ans、A、B、C の数を書くようにしてプログラムの流れを追っていけば分かるはずです。 また、Sub1~Sub3 の関数がどんな処理を行っているかも把握しておく必要があります。 最初は変数を紙(メモ帳)に記録するようにしてソースファイルの手順を追いかけます。 ・以上。
- gyokuto_tk
- ベストアンサー率66% (8/12)
順に手順を追っていくと、 ---------- L8 : Ans = A = B = C = 0 ⇒ 【Ans=0, A=0, B=0, C=0】 L9 : Sub1(&A)を 実行 L16 : A+=3 ⇒ Ans=0, A=3, B=0, C=0 L17 : Sub2(&A, 5) を実行 L20 : A+=5 ⇒ 【Ans=0, A=8, B=0, C=0】 L21 : 関数Sub2の戻り値は、A+5=13 関数Sub1の戻り値は、13 ここで、【Ans=0, A=8, B=0, C=0】 L10 : B = Sub2(&A, 8)を実行 (* 此処に注意) L20 : A+=A => 【Ans=0, A=16, B=0, C=0】 L21 : 関数Sub2の戻り値は、A+8 = 16+8=24 Bに代入して、【Ans=0, A=16, B=24, C=0】 L11 : C += Sub1(&B) + Sub3(&C) を実行 L16 : B+=3 ⇒ 【Ans=0, A=16, B=27, C=0】 L17 : Sub2(&B, 5) を実行 L20 : B+=5 ⇒ 【Ans=0, A=16, B=32, C=0】 L21 : 関数Sub2の戻り値は、32+5=37 関数Sub1の戻り値は、37 L24 : C+=5 ⇒ 【Ans=0, A=16, B=32, C=5】 L25 : 関数Sub3の戻り値は、5+1=6 Sub1(&B) + Sub3(&C) = 37 + 6 = 43となるので、C+=43 ⇒ 【Ans=0, A=16, B=32, C=48】 L12 : Ans = 16 + 32 + 48 = 96 ⇒ 【Ans=96, A=16, B=32, C=48】 ---------- となります。 ここで、注意しなければいけないのが、 上の手順の(*)の部分。 L10では、Sub2(&A, A)を実行しています。 ここで、Sub2の中で*pXを書き換えることでAの値は変わりますが、 【Subの2番目の引数Yの値は、関数実行時のAの値のまま】です。 (値渡しのため) そのため、始めから、L10でのAの値8を代わりに使って、 Sub2(&A, 8)と考えて計算しないと、答えがおかしくなります。 計算してみて迷ったら、とにかくデバッグプリント。 私もハマったので、 以下のソースのように毎行変数の値をチェックして動作を追い直しました。 ---------- 1 #include<stdio.h> 2 3 short Sub1(short *); 4 short Sub2(short *, short); 5 short Sub3(short *); 6 7 static const short *_Ans, *_A, *_B, *_C; 8 9 void main(){ 10 short Ans, A, B, C; 11 _A = &A; 12 _B = &B; 13 _C = &C; 14 _Ans = &Ans; 15 16 Ans = A = B = C = 0; printf("L%2d # Ans=%2d\tA=%2d\tB=%2d\tC=%2d\n", __LINE__, *_Ans, *_A, *_B, *_C); 17 Sub1(&A); printf("L%2d # Ans=%2d\tA=%2d\tB=%2d\tC=%2d\n", __LINE__, *_Ans, *_A, *_B, *_C); 18 B = Sub2(&A, A); printf("L%2d # Ans=%2d\tA=%2d\tB=%2d\tC=%2d\n", __LINE__, *_Ans, *_A, *_B, *_C); 19 C += Sub1(&B) + Sub3(&C); printf("L%2d # Ans=%2d\tA=%2d\tB=%2d\tC=%2d\n", __LINE__, *_Ans, *_A, *_B, *_C); 20 Ans = A + B + C; printf("L%2d # Ans=%2d\tA=%2d\tB=%2d\tC=%2d\n", __LINE__, *_Ans, *_A, *_B, *_C); 21 printf("Ans=%d:A=%d:B=%d:C=%d\n",Ans, A, B, C); 22 } 23 24 short Sub1(short *pX){ 25 *pX += 3; printf("L%2d # Ans=%2d\tA=%2d\tB=%2d\tC=%2d\n", __LINE__, *_Ans, *_A, *_B, *_C); 26 return Sub2(pX, 5); 27 } 28 29 short Sub2(short *pX, short Y){ 30 *pX += Y; printf("L%2d # Ans=%2d\tA=%2d\tB=%2d\tC=%2d\n", __LINE__, *_Ans, *_A, *_B, *_C); 31 return *pX + Y; 32 } 33 34 short Sub3(short *pX){ 35 *pX += 5; printf("L%2d # Ans=%2d\tA=%2d\tB=%2d\tC=%2d\n", __LINE__, *_Ans, *_A, *_B, *_C); 36 return *pX + 1; 37 } ----------
- asuncion
- ベストアンサー率33% (2127/6289)
各々の関数の引数にshort型へのポインタを含んでいます。 この扱いについては理解していらっしゃいますか?
お礼
ある程度は理解しているつもりですが、複雑なものになるとまだちょっと分かりません。
お礼
丁寧な回答をありがとうございます。これを参考にしてポインタを理解したいと思います。