|
|
|
| 2008/10/07 11:47||▲
|
|
|
今回は文字列の長さを調べるstrlen関数です。こういう単純な関数は、アセンブリ言語で記述すれば、より高速化できる場合もあるのですが、とりあえずはC言語で実装することにします。アセンブリ言語を使って、高速化の余地があるものについては、後ほど機会があれば扱いたいと思います。
それでは早速strlenの実装を行います。まずは、最も素直な実装からはじめてみましょう。
#include <stddef.h>
size_t strlen(const char *s) { size_t n; for (n = 0; *s != '\0'; s++, n++) ; return n; }
ご覧の通り、文字列sを最初から順番に調べ、ナル文字が見つかるまでnをインクリメントしています。この実装でも動作はしますが、あまり効率はよくありません。なぜなら、1回ループするごとに、2回もインクリメントを行っているからです。
ループの中はできる限り単純にし、1回あたりの処理を少なくした方が高速になります。したがって、
#include <stddef.h>
size_t strlen(const char *s) { register const char* ss; for (ss = s; *ss != '\0'; ss++) ; return ss - s; }
とすれば、ループ1回あたりのインクリメントは1回になります。ssをregister記憶クラスにしているのはお呪いのようなようなものですが、レジスタに割り付けられることを期待しているのは事実です。
このコードを、-mh -O2 -fomit-frame-pointerオプションを付けてコンパイルした結果は次の通りです。
_strlen: mov.l er0,er3 mov.b @er3,r2l .L8: mov.b r2l,r2l beq .L7 adds #1,er0 mov.b @er0,r2l bra .L8 .L7: sub.l er3,er0 rts
ターゲットがH8/300Hであることにご注意ください。H8のアセンブラに慣れていない方でも、何らかのアセンブリ言語の経験があれば、大筋で理解できるかと思います。er0とかer3というのは32ビットのレジスタです。r2lというは、32ビットレジスタer2の下位8ビットです。
つまり、引数のsがer0に、一時変数のssがer3に割り付けられていることが分かります。r2lは*ssを読み込んでナル文字と比較するために使われています。どうやら期待通りの結果になったようです。
アセンブリ言語で直接記述すれば、もう少し効率を上げることができそうですが、最初にお断りした通り、今は触れないことにしておきます。
|
| 2006/02/19 23:52|文字列操作|TB:0|CM:0|▲
|
|
|
コメント
|
|
コメントの投稿
|
|
|
|
|
トラックバック
|
トラックバックURLはこちら
http://libc.blog47.fc2.com/tb.php/30-4002f799
|
|
|
|
|
ホーム
全記事一覧
<< 前の記事
次の記事 >>
|