yohhoyの日記

技術的メモをしていきたい日記

配列要素数の取得 in 標準C

プログラミング言語Cの次期標準C2yでは、配列要素数を安全に取得する_Countof演算子が導入される。オペランドに配列型を要求すること以外は、構文規則的にsizeof演算子とほぼ同じ。

// C2y
int fibs[] = { 1, 1, 2, 3, 5, 8, 13, 21 };
static_assert(_Countof(fibs) == 8);  // OK

// 標準ヘッダ<stdcountof.h>で定義されるマクロ利用すると
// 小文字キーワード風に countof(fibs) と記述可能となる
#include <stdcountof.h>
static_assert(sizeof(fibs) == countof(fibs) * sizeof(int));
// C2y
void func(int data[100]) {
  // 関数パラメータ部の配列表記 int data[100] は
  // 実際には単なるポインタ型 int* data と解釈される。
  constexpr size_t N = _Countof(data);  // NG: ill-formed

  // sizeofを用いたハック (sizeof(data)/sizeof(data[0])) では
  // 正しい要素数を算出できず問題が潜在化・深刻化しうる。
  // _Countof演算子であれば誤りをコンパイル時に検出できる。
}

ノート:constexpr変数*1static_assertキーワードのネイティブ化*2はC23標準で導入された機能。

キーワード名_Countof+マクロ名countof決定までに様々な候補*3が検討されたが、最終的にCプログラマへの大規模アンケート結果*4に従ったとのこと。C言語仕様策定の歴史のなかでは珍しいパターン?

C2y WD N3550, 6.5.4.1, 6.5.4.5/p1, p5より一部引用。

Syntax
unary-expression:
  postfix-expression
  ++ unary-expression
  -- unary-expression
  unary-operator cast-expression
  _Countof unary-expression
  _Countof ( type-name )
  sizeof unary-expression
  sizeof ( type-name )
  alignof ( type-name )

Constraints
1 (snip) The _Countof operator shall only be applied to an expression that has a complete array type, or to the parenthesized name of such a type. (snip)

Semantics
5 The _Countof operator yields the number of elements of its operand. The number of elements is determined from the type of the operand. The result is an integer. If the number of elements of the array type is variable, the operand is evaluated; otherwise, the operand is not evaluated and the expression is an integer constant expression.

おまけ:提案文書(PDF)N3313には_Generictypeof演算子(→id:yohhoy:20220912)を活用した、C23向けの型安全な要素数取得マクロ定義例が載っている。後続の(PDF)N3325例示では配列型判定にGNU C組込関数__builtin_types_compatible_pを利用している。

関連URL

*1:https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3018.htm

*2:https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2934.pdf

*3:WG14提案文書でのキーワード変遷:_Lengthof [N2529] → elementsof [N3313] → nelementsof [N3325] → _Lengthof [N3369] → _Countof [N3469]

*4:回答数は約1000件。アンケート選択肢:lenof, lengthof, countof, nelemsof, nelementsof, extentsof