Cの配列の要素数

こんにちは、めのんです!

今回は「PHPプログラマーのためのC講座」ではありません。
このブログでは現在、「PHPプログラマーのためのC講座」を連載中ですけれど、ときどき違う内容も交えていきたいと考えています。
今回のようなプログラミング関係のコラムをはじめ、雑談的なものも投稿していきますね。

今日の話題はCの配列の要素数の数え方についてです。
ずっとCでプログラミングされていらっしゃる方であればおなじみの方法なので、とくに目新しい内容ではありません。

ではさっそく具体的なコードを見ていきましょう。

#include <stdio.h>

int main(void)
{
  int array[10];
  size_t n = sizeof(array) / sizeof(array[0]);
  printf("%zu\n", n);
}

こんな感じでsizeof演算子を使って配列の要素数を求めることができます。

以上なんですけど、これだけだとちょっと寂しいのでもう少しお話しさせてください。

sizeof演算子の評価結果はsize_t型になります。
size_t型というのがどんな型かというと

   size̲t
は,sizeof演算子の結果の符号無し整数型とする。

となっています。
冗談のようですが本当です。
要するにオブジェクトのサイズを表す型ということです。

sizeof演算子の評価結果はオペランドのバイト数になります(1バイトはchar型のサイズですね)。
オペランドに指定できるのは型または式です。

ところでsizeof演算子のオペランドが型の場合は必ず丸括弧 () で囲まないといけませんが、式の場合は丸括弧は不要です。
私は面倒なのでどっちの場合でも必ず丸括弧で囲むようにしています。

さて、先ほどのサンプルコードで使った配列の要素数を求める式をマクロにしておくと便利ですね。
本当は関数にできればいいんですけど、配列を関数に渡すとポインタになってしまうので無理なんです。
そういうわけで、大体は次のようなマクロを定義することになります。

#define COUNTOF(arg)  (sizeof(arg) / sizeof ((arg)[0]))

このマクロの問題は、うっかりargにポインタを渡してしまうと見当外れの評価結果になった上、何事も無かったように済ませてしまうことだと思います。
argがポインタだとコンパイルエラーにできる方法がないか考えてみたんですけど、いい方法が見つかりませんでした。
ポインタならOKで配列ならエラーにする方法ならGCC拡張を使えば簡単なんですけどね。

最後にちょっと違う話なんですけど、printf関数でsize_t型の値を書式化するには「%zu」を使います。
「%d」や「%u」だと未定義の動作になることが多いと思いますよ。

それではこれで終わります。
今回はコラムなのでこれぐらいの分量にとどめることにします。
これからもときどきコラムを書きますので読んでいただけると幸いです。