4
\$\begingroup\$

We all know the classic version of counting the number of elements in a C array: sizeof(a)/sizeof(*a)

But this is dangerous, because if used on a pointer it will return garbage values.

So I made this macro, utilizing gcc extensions. As far as I can tell, it works the way it is supposed to, which is causing compiler error when used on a pointer instead of array.

#define COUNT(a) (__builtin_choose_expr( \
                  __builtin_types_compatible_p(typeof(a), typeof(&a[0])), \
                  (void)0, \
                  (sizeof(a)/sizeof(a[0]))))
/* Only to demonstrate how to use the macro. It's not part of the code
   I want reviewed. */
int main(void)
{
    int arr[5];
    int *p;
    int x = COUNT(arr);

    // This line will yield the compiler error:
    //     error: void value not ignored as it ought to be
    int y = COUNT(p);
}

Any suggestions? Have I missed anything crucial?

\$\endgroup\$
6
  • 1
    \$\begingroup\$ klutt, Why int x and not size_t x, the type returned by the division? \$\endgroup\$ Feb 11, 2020 at 3:59
  • \$\begingroup\$ See also Array-size macro that rejects pointers. \$\endgroup\$ Feb 11, 2020 at 4:06
  • \$\begingroup\$ Why are you trying to write the value of a void on the last line of your main? What are you trying to illustrate here? \$\endgroup\$
    – Mast
    Feb 11, 2020 at 8:45
  • \$\begingroup\$ @chux-ReinstateMonica See comment. Also, I should have realized that a linux kernel developer already thought of this :) \$\endgroup\$
    – klutt
    Feb 11, 2020 at 9:10
  • \$\begingroup\$ @Mast Because that will fail. I want a compiler error if it is used on a pointer instead of an array. \$\endgroup\$
    – klutt
    Feb 11, 2020 at 9:11

1 Answer 1

5
\$\begingroup\$

We need to protect a when it's an expression - we've put parens around a[0] where we should have put them around a:

(sizeof(a)/sizeof(a)[0])

For the same reason, I think that the second typeof should be

typeof(&(a)[0])

I have to admit that I can't easily contrive an expression of array type where the parens make a difference, but better safe than sorry...

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.