局所変数、特に集成体を宣言した後、実際に必要かどうかに関わらず、必ずmemset関数でゼロクリアする人は大勢います。しかし、そんなコードを見かけたら、それを書いた人のコードはすべて疑ってかかった方がよいかもしれません。

まずは、次のコードをご覧ください。

よく見かけるコードですが、上のコードは、必ずしも期待した結果になるとは限りません。なぜなら、double型やポインタ型は、これらを構成する全ビットが0になったとしても、オブジェクトの値が0になるかどうかは分からないからです。

確かに、ほとんどの処理系では上記のコードでも問題なく、そして期待通りに動作します。しかし、それはあくまでも”たまたま”動いているに過ぎません。そうした不安定な要素をなくすために行った初期化が、かえってコードを怪しくしてしまっているのです。

C言語で、単に集成体の全要素をゼロクリアしたいだけであれば、

とすれば十分です。このように書くと、おそらく次のような反論が返ってくることでしょう。「その方法では、構造体の詰め物がゼロクリアされない」と。しかし、構造体の詰め物にアクセスして、言語仕様上保証される結果を期待することには無理があります。

構造体の詰め物をゼロクリアしたい理由は、多くの場合、memcmp関数を使って一致判定を行いたいことが理由でしょう。しかし、整数型以外をゼロクリアしても結果が保証されないのと同様、比較の場合もうまくいくとは限りません。具体的には、内部表現が異なる場合でも、値としては同じになるかもしれないからです。

あるいは、こんな反論も聞こえてきそうです。「memset関数を使った方が効率がよい」と。本当に効率がよいかどうかは実測してみるか、コンパイル結果を見て、ステップ数を計算してみてください。必ずしもmemset関数の方が効率がよいわけではないことに気付くはずです。

仮にmemset関数の方がずっと効率がよかったとしても、こんな汚い方法による最適化は最終手段にすべきです。それに、こんな初期化はそれ自体が不要な場合もあり、単なる”おまじない”に過ぎないことも多いのです。

ところで、先ほどはC言語の例でしたが、C++であれば、

のように波括弧の中に0をひとつも書かなくてもかまいませんし、C++11以降であれば、

のように書くこともできます。