聴くとムオーンというよりはブホーという音ですね。メモリ参照は後にする王様がリンクしているので、まじめに書いてみる(意図を誤読しているかも知れないけどまあいいや)。なんとなく16K境界で発現しそうに思ったら、思いのほか伸びたので途中から別の話になってたし。問題は指定された長さのメモリーブロック内の文字走査の書き方だ。元のポインタ値を保持するためにインクリメンタル用ポインタを別に用意する。0が現れるか指定長に到達するまでpを後ろへ移動する。元のポインタとの差=ターゲット文字までか、または元のメモリーブロックの長さを返す}バグは、for文の条件式にある。今、foobarに長さ2バイトのメモリーブロックを与えるとする。ターゲット文字(この例では0)は含まない。2));ここで、aがポイントするアドレスを0とする。forの最初の時点でiは0、pは0、lenは2となっている。条件式を実行すると、pは0(ということはa[0]なので'\xff')、iは0なので条件は成立せず、継続式に制御が移り、pは1、iは1となる。条件式を実行すると、pは1(ということはa[1]なので'\xff')、iは1なので条件は成立せず、継続式に制御が移り、pは2、iは2となる。----)仮にa[2]相当のメモリー位置の内容が0ならforステートメントを抜ける。なければiは2で、lenの2と等しいためforステートメントを抜ける。現在のpの値2から、ptrの値0を引いた値2が戻り値となる。lenにより最終的にforステートメントを抜けることができるからだ。lenの時点での条件式の左項は、未割当メモリーに対する参照となり、バグが(見えるかたちで)発現する。'\0'のように、最初に長さの比較をし、次に(左項により*pが安全なアクセスであることを確認できた後に)メモリーの参照を行う。この形式で記述できるのは、Cが、条件式をショートカットするからだ。ショートカットにより、左項の条件が満たせなかった場合、つまり、iがlenと等しい=pが与えられたメモリーブロックの範囲を超えた位置を指している場合は右項の実行を回避できるからだ。みたいな条件式を書いてIndexOutBoundExceptionみたいな例外で死んだことがあるので、言語仕様を読むのは重要ですなぁと)あと、JavaとかC#とかインクリメンタル操作とかが可能なポインタが無い言語では、同じようなことをするには配列を使うしかないので、当然、IndexOutOfBoundExceptionみたいな例外をさっさと食らえるので(ユニットテストとかまじめにしていれば)この手のバグが入り込む余地はない。いうわけで、ああいう言語は楽ですなぁと思う。Cが低レベルなわけ忘れてたけど、上のバグは慣れればすぐわかるのだが、しかし犯しやすい。lenのほうが自然な記述だからだ。いうのは、ここでやりたいこと、主要な機能は、iがlenの長さになるまで、ではない。*pに'\0'が見つかるまで、だ。関数コメントを1行で書けば、「与えられた文字列内の'\0'までの長さか、見つからなければ(と条件つきで)その長さを返す」になるだろう。重要な機能を最初に書くのは、むしろ良い習慣だから、或る程度プログラムが書ければ逆に書いてしまうし、プログラムの機能を読めば見過ごしてしまいかねない。いうわけで、String#indexOfだとか、Array#find(あるかどうか知らないけど)とかのメソッドが用意された言語のほうが良い言語だし、自前でループ書くより用意された(名前がついた)メソッド使え、というような話になるのだ、と思う(けど他にも理由はあるから言い切れない)。そのあたりが、Cのだめっぷりということになるんだけど、逆にその生々しさがCの魅力でもあってとっても悩ましい。[この場合は、そういう方法もあるのですね。