Introduce and use the cool C2y `countof` operator
Last year I rewrote the C code to use declarations in for loops init-clauses in #13289 (a C99 feature!). This year, I propose a fast-forward in time to introduce a new C2y operator, _Countof. This operator counts the number of elements in an array. If the operand is not an array, it produces a compilation error. This adds a bit of type safety and consistency.
int dracula[n];
_Countof(dracula); // returns n elements, not n bytes
- N3369 - New
_Lengthof()operator (v4) (later renamed to_Countof); - GCC Determining the Number of Elements of Arrays;
- Clang C2y
_Countof.
See also, for __has_feature and __has_extension:
The trend since C11 seems to introduce new operators as _Operator (as the _[A-Z] prefix is reserved by the standard for identifiers), introduce macros as #define operator _Operator in a new <std….h> header, and in a later revision turn the macro into a regular keyword and make the header a no-op. If we were to include the lowercase identifier in a public header, it could interact badly with other projects also defining it. Regarding the spelling, my preference goes to using countof over _Countof or CAMLcountof. I've tried to come up with a backward and forward compatible definition of countof, that I've kept private under CAML_INTERNALS.
This patch was generated using Coccinelle, with the semantic patch below. Only the #define CAML_INTERNALS were manually added, as needed.
@n@
identifier NSPEEDS,speedtable;
@@
- #define NSPEEDS (sizeof(speedtable) / sizeof(speedtable[0]))
@@
identifier n.NSPEEDS;
@@
- NSPEEDS
+ countof(speedtable)
@m@
identifier ARR_SIZE,E;
@@
- #define ARR_SIZE(a) (sizeof(a) / sizeof(*(a)))
@@
expression E;
identifier m.ARR_SIZE;
@@
- ARR_SIZE(E)
+ countof(E)
@@
type T;
T[] E;
@@
- (sizeof(E)/sizeof(*E))
+ countof(E)
@@
type T;
T[] E;
@@
- (sizeof(E)/sizeof(E[...]))
+ countof(E)
@@
type T;
T[] E;
@@
- (sizeof(E)/sizeof(T))
+ countof(E)
@@
type T;
const T[] E;
@@
- (sizeof(E)/sizeof(T))
+ countof(E)
Kudos for using Coccinelle to apply the change! I like your argument for the name of countof, but I'm slightly worried at the header - misc.h is pulled in by so many other headers, and saying "it's guarded by CAML_INTERNALS" feels a bit like the argument used in glibc 2.34 to justify changing SIGSTKSZ which led to #10266 (the rationale was that it only happened if GNU_SOURCE was defined IIRC), and I'm still a bit scarred by that.
Given that we only need it in the C sources, perhaps that can just go in a separate internal header? (misc_internal.h or something?!) - still guarded by CAML_INTERNALS, but just not risking being pulled in arbitrarily by other headers.
Yes, a private header is the better alternative that I didn't dare to suggest, but has my preference too. I'll push a revision with a new header.
I am missing what was wrong with 00d0f00a55cefc regarding CAML_INTERNALS, which is indeed meant to handle internal definitions (https://ocaml.org/manual/5.4/intfc.html#s:c-internal-guidelines). Users know they should not use it (unless they know what to do and are ready for their program to break in future OCaml versions). In contrast, _GNU_SOURCE is a documented glibc feature test macro to invoke GNU-specific extensions.