Hi Bruno,
On Mon, Jun 02, 2025 at 02:32:46PM +0200, Bruno Haible wrote:
> Hi Alejandro,
>
> > - I have plans for improving _Countof as a GNU extension to work on
> > array parameters to functions. I mean making this possible:
> >
> > wchar_t *
> > wmemset(size_t n; wchar_t wcs[n], wchar_t wc, size_t n)
> > {
> > for (size_t i = 0; i < countof(wcs); i++)
> > wcs[i] = wc;
> > return wcs;
> > }
>
> The sizeof operator does not work well in this case, right? So that would be
> a case where countof works _better_ than sizeof.
Yes, that's correct. _Countof will provide functionality that is not
currently available in C programs at all. I believe this will make many
of those complaints that people do that "C arrays are unsafe" be
obsolete.
> > What worries me of adding countof to C++ is that they may use it in
> > some way that could preclude my planned extension. So I'll not
> > remind C++ people about this until I made sure my extension is
> > deployed in both GCC and Clang, and maybe in ISO C.
>
> While I understand this, it still means that gnulib — which strives to make
> the same code usable in C++ like in C — will probably have to override
> <stdcountof.h> roughly like this:
>
> #ifdef __cplusplus
> template <typename T, size_t N>
> constexpr size_t countof(T const (&)[N]) {
> return N;
> }
> #else
> # define countof _Countof
> #endif
You'll need to take into account the case where _Countof is not
available, and fall back to sizeof division (which won't work with array
parameters, but at least it will work in most cases). I'd do something
like this:
#ifdef __cplusplus
template <typename T, size_t N>
constexpr size_t countof(T const (&)[N]) {
return N;
}
#elif __has_include(<stdcountof.h>)
# include <stdcountof.h>
#else
# define countof(a) (sizeof(a) / sizeof((a)[0]) + must_be(is_array(a)))
#endif
must_be(is_array(a)) is a trick to assert that the argument is an array.
<https://stackoverflow.com/questions/37538/how-do-i-determine-the-size-of-my-array-in-c/57537491#57537491>
> (And I have no idea whether this definition will work for variable-sized
> arrays and for function parameters.)
I'm not sure if that C++ implementation would work with VLAs or array
parameters. However, as long as it results in a compilation error, I'm
not worried at all. What would worry me is if it would silently
misbehave.
I suggest that if you implement a countof alternative, you run the
testsuite that I added in GCC for the operator.
$ find gcc/testsuite/ | grep countof
gcc/testsuite/gcc.dg/countof-pedantic.c
gcc/testsuite/gcc.dg/countof-zero.c
gcc/testsuite/gcc.dg/countof-no-compat.c
gcc/testsuite/gcc.dg/countof-compat.c
gcc/testsuite/gcc.dg/countof-vla.c
gcc/testsuite/gcc.dg/countof-vmt.c
gcc/testsuite/gcc.dg/countof.c
gcc/testsuite/gcc.dg/countof-compile.c
gcc/testsuite/gcc.dg/countof-pedantic-errors.c
gcc/testsuite/gcc.dg/countof-stdcountof.c
gcc/testsuite/gcc.dg/countof-zero-compile.c
You should adapt them to test countof instead of _Countof, and you'll
see the comment at the top to see which compiler flags are appropriate.
If that testsuite passes, your implementation should be safe. A few
things will not work with the sizeof division, as I'm testing that
_Countof is smarter than that and makes some things be integer constant
expressions where sizeof is unable to do that; but you can ignore those
few test cases.
Have a lovely day!
Alex
--
<https://www.alejandro-colomar.es/>
signature.asc
Description: PGP signature
