遊月さんのC言語と遊ぶ strchr

こちらの記事がきっかけで。
C言語を盛り上げるためにも、たくさんの記事を書きましょう!

そんでもって、ちょっと変えてみたわけです。

const char* c_strchr(const char* s, int ch) {
  for (;;) {
    if (*s == '\0') {
      return NULL;
    }
    if (*s == (char)ch) {
      return s;
    }
    s++;
  }

  return NULL;
}


オート変数をなくしてみた

次の2つのオート変数をなくしてみた。

・t_s
・s_ch

「オート変数をなくす」と聞くと「いいんじゃね」という感じなんだが、ちょっと悩ましい面もあったりする。

オート変数 t_s

 これをなくすと、関数の途中でリターンしなきゃならない。returnを1つにまとめたければローカル変数は必須である。
 このコードそのものは、途中でreturnしても問題はないわけであるが、returnをあちこちにばらまくと改修するときに悩む。あちこちでリターンしていることを忘れて妙なバグを埋め込むことも、ある。この関数ではあり得ないかもしれないが、万一これに排他制御を入れようものなら、泣く。「誰だ! こんなにあちこちにreturn文を入れやがって」と、恨み言の1つも言いたくもなろうというものだ。
 ということも思いつつ、最近は変数を減らしたい思いが強い。

オート変数 s_ch

 こちらの変数もなくしたらはなくしたで、なんとなく微妙な感じである。これをなくしてしまうと「*s」を2回書かなきゃならなくなる。「*s」くらいたいしたことないでしょうと思うかもしれないが、実際、C言語のコード的にはたいしたことではないんだが、「*s」というのは実は演算をしている。「*」は間接参照するための演算子なんである。アドレス計算は済んでいるので、あとはメモリにアクセスするだけではあるんだが、どんくさいコンパイラだと、

スタックからアドレスを取り出して間接参照し、
2度目も同じくスタックからアドレスを取り出して間接参照する

というような、同じこと2回やるなよ的なコードが出来上がる。かもしれない。オート変数に待避しておくのとどれだけ差がでるのかはわからないが、ループすると塵も積もれば山となるで案外にちょっとしたことがそこそこの処理速度の差につながることもないではない。と思いつつ、こんなコードもあるんですけど、ということで。


elseをなくしてみた

if (*s == '\0') {
    return NULL;  ①
}
if (*s == (char)ch) {
    return s;
}

この太字のところの①を通ったら、もうその下の行には行き着かないわけで。だからもう、elseはいらないということになる。


*sとs++にわけてみた

そもそも、私はこの演算がどうにも苦手で。

*s++

いったいこれは

*(s++) なのか、はたまた (*s)++ なのか

あるいはまた

s++してから*sなのか、はたまた *sしてからs++なのか

大いに悩むわけで。だから、分けた(笑)。
「s-1」をしなくてすむということもある。


以上である。
「いや、そりゃ違うでしょ」意見は大いに歓迎である。


この記事が気に入ったらサポートをしてみませんか?