関数の引数として文字列を渡すとき

僕は関数の引数で文字列を渡して処理をするライブラリを書くことが多いです。

他人に使ってもらうことが多いライブラリは効果が大切ですが、
分かりやすさも大切なので引数を少なくしたいと思っています。

ですが、文字列処理をする関数は引数を少なくすると、「受け取った文字列のbyte長を取得する」とか「結果を格納するバッファ領域を確保する」とか、引数を受け取ったあとの処理が余計に増えてしまいがちです。

しばらく悩んでいましたが、最近は「処理を高速化するためなら引数が増えてもいいや」と思うようになりました。
簡単なものには裏ができちゃいますからね。。@echizentm さんと雑談してたら吹っ切れました。

以下には、関数の引数として文字列を渡す際に、最近やっている対処方法をメモします。


文字列や配列は長さとセットで渡す


- 文字列や配列を引数として渡す時には、その長さも渡す。
-- forやstrlenを減らしたい
-- 引数が増えるのは別に良い

文字列の配列は各要素のbyte長の計算を事前にする


- 文字列の配列から『「文字列の配列の各要素のbyte長」の配列』を作る。
- 事前計算で作ったテーブルを極力活用する。

処理結果を格納する領域の扱いは柔軟に


以下の両方に対応する。必要がなければ片方だけ。

- 結果を格納する領域のポインタを受け取って結果を詰め込む
- 内部的に領域を**allocしてその領域のポインタを返す。事後にfreeしてもらう。
-- openという単語を含む関数名にするとcloseしなきゃいけない気分になる?

領域の初期化は最小にする


- 領域全体を初期化しない。なるべく使った部分だけ初期化する
-- memsetのコストは割と大きい
-- 自前でアロケータを書いて領域の初期化がいらないようにするのが究極か

値は出来るだけ使い回す


- 極力、値のコピーや変数の定義をしない
- 値の使い回しで実装が複雑になる場合はなるべく避ける

なるべくmemcpyを使う


- strncpyやstrncatなどの複雑な関数ではなく、なるべくmemcpyで済むように頑張る。

必要なら戻り値で情報を返す


- 処理後に使い回したい計算が必要な値は、関数の戻り値で返すのが好き
-- 戻り値が駄目な場合は、結果を格納するために引数が一つ増える。。。

引数の多い関数にはラッパーを用意する


- とある引数から計算することで他の引数を得られるなら関数内で計算できる引数を省略したAPIを持つラッパーを用意しておく
-- 関数の内部で引数の多い関数を呼ぶための足りない引数を生成する。




処理速度に定評のあるオープンソフトなアプリケーションを見ると、処理を高速化するためにやっていることが見つかったりします。
そういうのに気付くたびにメモに追記します。

ハッカーのたのしみ―本物のプログラマはいかにして問題を解くか

[Amazonで詳細を見る]


[2010-05-27]:追記。
ラッパーを用意する、というのを書き忘れていた。ラッパーは重要。


投稿者:としのり  日時:23:59:59 | コメント | トラックバック |
blog comments powered by Disqus