関数の呼び出しについて

これは公開用ではありませんので、ググってきた方は戻ることをおすすめします。

 

関数の呼び出しについて


何気なく使っている関数ですが、どうして関数は処理を終えた後、無事呼び出し元に戻れるのでしょうか?

関数の呼び出しとはいわば、呼び出した地点から、関数の本体へジャンプして、処理をして、元の場所に戻ることです。

 

これを説明するには、関数がコンピューターの中で実際にどのように呼ばれているのかを考える必要があります。

難しい説明は抜きにします。

 

プログラムというのはコンピューターのメモリ上に展開されます。メモリには番地というのがあって、それを用いて、メモリ上の任意のデータにアクセスすることができます。

コンピューターはプログラムを実行する際に、メモリ上の十分な場所に、プログラムを一続きになるように展開します。

 

そのあとに、コンピューターはプログラムカウンタという現在実行している番地を記録する場所に、実行したいプログラムの一番最初の番地を登録します。

 

後は簡単です。コンピューターはプログラムカウンタの示す番地のデータを取ってきて処理をします。処理が終わったら、プログラムカウンタの指す番地を一つ先に進めます。つまり、今実行している番地の次の番地を指すようにします。

 

このロジックを繰り返すことで、コンピューターはプログラムを順々に実行していきます。

プログラムの終了を示すデータの入った番地のデータを読み出した地点で、コンピュータはプログラムの実行を終了させます。

 

ところで、コンピューターにはプログラムカウンタのほかに、様々な記憶領域があります。その一つに、積みゲーのごとく、番地を積んでおいておくスタックという場所があります。つまり、最近積んだ番地が一番上にあって、それをとってどうこうすることができます。どうこうした番地はスタックから取り除かれて、その一個下に積んであった番地が、一番上にきます。

 

関数はこのスタックを利用しています。

プログラムカウンタの指す番地のメモリに関数の呼び出しをする命令が書かれていたとします。

コンピュータはこのときプログラムカウンタの内容を(つまり指し示している番地を)スタックに積みます。あとは関数の始まりのデータのある番地を指すようにプログラムカウンタを書き換えます。そうすればコンピュータはその関数を実行することができます。

 

コンピュータはreturn命令のある番地を読み込んだときに関数を終了します。PHPにおいてはreturnのない関数でも、関数の最後にreturnが自動的に書かれます。

 

return命令を読み込んだとき、コンピュータはスタックから番地を取り出します。取り出した番地の一つとなりの番地をプログラムカウンタに書き込みます。これはどういうことかというと、呼び出し命令の書かれていた番地の隣の番地を実行するようにしたと言うことです。

 

こうして無事に関数から帰ってこれたわけです。

 

つづく

Works : MarkdownViewerQt - Markdownビューワー(Linux + Qt)

qlmarkdownみたいな手軽さでMarkdownを見られたら良いなと思ってqtで作成したものです.
今回は紹介だけで, ビルド可能なパッケージはまだ準備出来ていません.

追記:準備ができました.

続きを読む

LuaSDL2: ビルドできない件

LuaSDL2とはLuaでSDL2を利用するためのライブラリであるが, gitからcloneしてビルドしようとするとうまく行かない.

問題

/home/hoge/tmp/luasdl2/src/window.c: In function ‘hitTestCallback’:
/home/hoge/tmp/luasdl2/src/window.c:915:2: warning: implicit declaration of function ‘lua_geti’ [-Wimplicit-function-declaration]
  lua_geti(cd->L, LUA_REGISTRYINDEX, cd->ref);
  ^
/home/hoge/tmp/luasdl2/src/window.c: In function ‘l_window_setHitTest’:
/home/hoge/tmp/luasdl2/src/window.c:950:10: error: void value not ignored as it ought to be
  if ((ut = lua_getuservalue(L, 1)) == LUA_TUSERDATA) {
          ^
/home/hoge/tmp/luasdl2/src/window.c:947:6: warning: variable ‘ut’ set but not used [-Wunused-but-set-variable]
  int ut;
      ^
CMakeFiles/SDL.dir/build.make:590: ターゲット 'CMakeFiles/SDL.dir/src/window.c.o' のレシピで失敗しました
make[2]: *** [CMakeFiles/SDL.dir/src/window.c.o] エラー 1
CMakeFiles/Makefile2:67: ターゲット 'CMakeFiles/SDL.dir/all' のレシピで失敗しました

warningは良いとして, errorについてみてみる.
lua_getuservalue関数はvoidらしい.
こんな単純なミスを犯すだろうか?
Lua5.2のリファレンスを見てみてもこの関数はvoidを返す.
ではLua5.3では?
intを返すのだ.

解決策

  • liblua-5.3-dev (Ubuntuの場合)をインストール
  • cmake .. -DWITH_LUAVER=53 でcmakeする

これで出来ました.
ちなみにgithubのissueに上がっています. 調べが甘かったです. apiリファレンスやヘッダファイルを調べるはめになりました.

cmakeのデフォルトがLua5.2らしいけど, デフォルトでビルドすると失敗するのは解決した今なら笑える冗談です. (バグだというのは重々承知の上で)

以上.

C# : NAudio と 高速フーリエ変換(FFT)

NAudioについての日本語の記事が少ないので備忘録も兼ねてNAudioでのFFTのやり方を書きます.

今回の目標はマイクから取得した音をフーリエ変換することです.

いかんせん自分が信号について素人なので、記事の対象読者は次の通りです。

  • 理屈に詳しくないが、フーリエ変換を活用したい。
  • NAudioの日本語での解説が見たい。

読者がゼロにならないことを願います。

続きを読む

プログラミング : リーダブルコードを読もう

単純に本の紹介です.

www.oreilly.co.jp

プログラミングをする者にとって一度は読んでおきたい本の一冊だと思います.
基本的なことしか書かれていない.しかし,それがいい.

プログラムをReadable(読めるように)書くにはどうしたらよいかをわかりやすく説明しています.
昨日の自分は他人.独りプログラマーでもぜひ読むべきだと思います.
上級者には面白みもないようですが...

言語がごっちゃの本なので,ちょっとほかの言語も読めないときついかもしれません(ただし,使われている文法はほぼ基本的なもの.C言語ができれば読破はたやすいでしょう)

以上 Raptor でした.

プログラミング : 関数を使う

タイトルを見て、
「あぁ、モジュール化が大事なのね。」
と思った方は、もう少し読んでみてください。
ここでいう関数とは、
「ある入力に対してただ一つだけの値を取る射」
という、数学の意味での関数です。
プログラミングにおいて強力なのは繰り返し構文ですね。
これさえあれば、どんな反復作業もシンプルにかけます。

しかし、ある作業に関しては、繰り返しよりも、数学的に導き出せる関数の方が、いい選択になるのだ、と、ここでは書きたいわけです。

例としては、総和が挙げられます。
1から10の和を求める時、明らかに繰り返しよりも、台形公式の方が計算量が減りより良いです。小数を扱う時は、特に誤差に気をつけなくてはならない繰り返しよりも精度が高いです。

ゲームなどで、キャラクターや弾の位置を決める時、もし、プレイヤーの行動が影響しないのであれば、関数で位置を決定する方が、リプレイの情報量が減ったり、記述がシンプルになったり、複雑なことができます。(時間を止めたり、巻き戻したりするのは、関数だと時間tをいじるだけでできます。)

また、関数はただ一度の計算で値を算出できるので、記述はシンプルになるし、場合によっては処理速度も向上します。

もし、時間に余裕があるならば、処理内容を表す関数を考えてみると、より良いプログラムができるかもしれません。

まとめ
精度が求められたり、シンプルに変わったことを実装したい時は、一度数学的な式で表せないかを考えてみると良い。また、普段のプログラムでも数学的な式で表す工夫をすると、良いものができることがある。

以上Raptorでした。