C言語で分からんとこがあったのでトレースしてみたら、うーん納得。

年末年始でC言語を習得する予定だったけど、予期せぬ高熱の為に少し予定を変更せざるを得なかったのでござーる。とかなり大げさに書いてみる。

 

ってことで、基本が終わって、演算、ループ、配列とスラスラと(基本的なことしかしてないからね)進んで関数のとこまで進んだんだけど、どうもよく分からん式に遭遇した。
ちなみに関数ではなくて、ただの式で分からんとこが出てきた。

バカで悲しいなあってことはこの際抜きにして、トレースってもんを初めてやってみたので、載せてみる。
トレースって何って、要はプログラムを追ってみただけなんがね。

環境はScientificLinuxのgccです。教材は柴田望洋さんの入門書なり。
トレースツールをググってみたらgdbというものがあるらしい。
yumで入ります。slなら。っつか、Gがついてるし、CentOSやらでも多分なんでもいけるんでないかな。

謎だったソースはこんな感じ。一部だけなので分からないかもだけど、正の数を入力して、それをまるっと逆にして表示するというプログラムです。

    int tmp=0;

    if (num > 0){
        do {
            tmp = tmp * 10 + num % 10;
            num /= 10;
        } while (num > 0);
    }

なぜ0を代入して計算してるんだ~ってことが分からんかった。

    int tmp=0;

    if (num > 0){
        do {
            tmp += num % 10;
            num /= 10;
        } while (num > 0);
    }

これでいいんじゃないの?って思ってしまったわけです。

では1個目のプログラムからトレースした結果を載せてみます。

トレース開始します。

[root@localhost program]# gdb a.out
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-60.el6_4.1)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/program/a.out...done.

問題の行で止まるようにします。

(gdb) break 22
Breakpoint 1 at 0x4005d9: file list6-9.c, line 22.

プログラムを動かします。

(gdb) run
Starting program: /root/program/a.out
正の数を入れてね35

Breakpoint 1, rev_int (num=35) at list6-9.c:22
22                              tmp = tmp * 10 +  num % 10;
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.x86_64

問題の部分で止まってます。
今はtmpに入ってるのは0です。

(gdb) print tmp
$1 = 0
(gdb) next
23                              num /= 10;

分かりにくいですが、さっきの式を実行すると、tmpに5が入ります。ここまでは問題ないですね。
1行づつ進めてみます。

(gdb) print tmp
$2 = 5
(gdb) next
24                      } while (num > 0);
(gdb) print tmp
$3 = 5
(gdb) next

Breakpoint 1, rev_int (num=3) at list6-9.c:22
22                              tmp = tmp * 10 +  num % 10;
(gdb) print tmp
$4 = 5
(gdb) next
23                              num /= 10;

これで元の35から53に変わりました。

(gdb) print tmp
$5 = 53

では、これでもいいじゃないの?って次思った方でトレースします。うう、ちょっと恥ずかしい。

Breakpoint 1, rev_int (num=35) at list6-9.c:22
22                              tmp += num % 10;
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.x86_64
(gdb) print wmp
No symbol "wmp" in current context.
(gdb) print tmp
$1 = 0
(gdb) next
23                              num /= 10;

うん、ここまでは問題なし。

(gdb) print tmp
$2 = 5
(gdb) next
24                      } while (num > 0);
(gdb) print tmp
$3 = 5
(gdb) next

ループ~

Breakpoint 1, rev_int (num=3) at list6-9.c:22
22                              tmp += num % 10;
(gdb) print tmp
$4 = 5
(gdb) next
23                              num /= 10;

なるほどね!と、ここでやっと・・・。気づくのが遅いにょ。ばよえーん。

(gdb) print tmp
$5 = 8
(gdb)

終わったら、ないないしましょう~。

(gdb) quit
A debugging session is active.

        Inferior 1 [process 6119] will be killed.

Quit anyway? (y or n) y

さてさて、2巡目を考えてやっとわかりましたとさ。
はぁ、やれやれだぜ。的な。

あれ、今回はgdbの使い方だっけ??

はてなー。

 

Related Posts


投稿者: Takeken

インターネット利用者のITリテラシーを向上したいという設定の2次元キャラです。 サーバー弄りからプログラミングまで手を付けた自称エッセイストなたけけんの物語。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です