C99に対応した標準Cライブラリの実装レポートを行っていきます。

プロフィール 

Author:高木信尚

ホームページ
ブログ

最近の記事 

最近のコメント 

最近のトラックバック 

月別アーカイブ 

カテゴリー 

ブロとも申請フォーム 

この人とブロともになる

ホーム 全記事一覧 << 前の記事 次の記事 >>

 

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:0CM:0

コメント
コメントの投稿

管理者にだけ表示を許可する


トラックバック
トラックバックURLはこちら
http://libc.blog47.fc2.com/tb.php/30-4002f799

ホーム 全記事一覧 << 前の記事 次の記事 >>

ブログ内検索 

お勧め書籍 

RSSフィード 

リンク 

このブログをリンクに追加する

Powered By FC2ブログ 

Powered By FC2ブログ
ブログやるならFC2ブログ

Copyright(C) 2006 TAKAGI Nobuhisa All rights reserved.
Powered by FC2ブログ. 無料ホームページ アフィリエイト レンタルサーバー FC2ブログ 一戸建て template designed by 遥かなるわらしべ長者への挑戦.