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/>

Attachment: signature.asc
Description: PGP signature

Reply via email to