Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8643199
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 12, 20262026-06-12T11:58:25+00:00 2026-06-12T11:58:25+00:00

Every C programmer can determine the number of elements in an array with this

  • 0

Every C programmer can determine the number of elements in an array with this well-known macro:

#define NUM_ELEMS(a) (sizeof(a)/sizeof 0[a])

Here is a typical use case:

int numbers[] = {2, 3, 5, 7, 11, 13, 17, 19};
printf("%lu\n", NUM_ELEMS(numbers));          // 8, as expected

However, nothing prevents the programmer from accidentally passing a pointer instead of an array:

int * pointer = numbers;
printf("%lu\n", NUM_ELEMS(pointer));

On my system, this prints 2, because apparently, a pointer is twice as large as an integer. I thought about how to prevent the programmer from passing a pointer by mistake, and I found a solution:

#define NUM_ELEMS(a) (assert((void*)&(a) == (void*)(a)), (sizeof(a)/sizeof 0[a]))

This works because a pointer to an array has the same value as a pointer to its first element. If you pass a pointer instead, the pointer will be compared with a pointer to itself, which is almost always false. (The only exception is a recursive void pointer, that is, a void pointer that points to itself. I can live with that.)

Accidentally passing a pointer instead of an array now triggers an error at runtime:

Assertion `(void*)&(pointer) == (void*)(pointer)' failed.

Nice! Now I have a couple of questions:

  1. Is my usage of assert as the left operand of the comma expression valid standard C? That is, does the standard allow me to use assert as an expression? Sorry if this is a dumb question 🙂

  2. Can the check somehow be done at compile-time?

  3. My C compiler thinks that int b[NUM_ELEMS(a)]; is a VLA. Any way to convince him otherwise?

  4. Am I the first to think of this? If so, how many virgins can I expect to be waiting for me in heaven? 🙂

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-12T11:58:26+00:00Added an answer on June 12, 2026 at 11:58 am

    Is my usage of assert as the left operand of the comma expression valid standard C? That is, does the standard allow me to use assert as an expression?

    Yes, it is valid as the left operand of the comma operator can be an expression of type void. And assert function has void as its return type.

    My C compiler thinks that int b[NUM_ELEMS(a)]; is a VLA. Any way to convince him otherwise?

    It believes so because the result of a comma expression is never a constant expression (e..g, 1, 2 is not a constant expression).

    EDIT1: add the update below.

    I have another version of your macro which works at compile time:

    #define NUM_ELEMS(arr)                                                 \
     (sizeof (struct {int not_an_array:((void*)&(arr) == &(arr)[0]);}) * 0 \
      + sizeof (arr) / sizeof (*(arr)))
    

    and which seems to work even also with initializer for object with static storage duration.
    And it also work correctly with your example of int b[NUM_ELEMS(a)]

    EDIT2:

    to address @DanielFischer comment. The macro above works with gcc without -pedantic only because gcc accepts :

    (void *) &arr == arr
    

    as an integer constant expression, while it considers

    (void *) &ptr == ptr
    

    is not an integer constant expression. According to C they are both not integer constant expressions and with -pedantic, gcc correctly issues a diagnostic in both cases.

    To my knowledge there is no 100% portable way to write this NUM_ELEM macro. C has more flexible rules with initializer constant expressions (see 6.6p7 in C99) which could be exploited to write this macro (for example with sizeof and compound literals) but at block-scope C does not require initializers to be constant expressions so it will not be possible to have a single macro which works in all cases.

    EDIT3:

    I think it is worth mentioning that the Linux kernel has an ARRAY_SIZE macro (in include/linux/kernel.h) that implements such a check when sparse (the kernel static analysis checker) is executed.

    Their solution is not portable and make use of two GNU extensions:

    • typeof operator
    • __builtin_types_compatible_p builtin function

    Basically it looks like something like that:

    #define NUM_ELEMS(arr)  \
     (sizeof(struct {int :-!!(__builtin_types_compatible_p(typeof(arr), typeof(&(arr)[0])));})  \
      + sizeof (arr) / sizeof (*(arr)))
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Aspiring programmer here! You can skip this part if you find it irrelevant. Im
I know this is a question that every programmer should know, but I do
New Rails programmer here. There is probably a pretty simple solution to this, but
Every programmer here knows about ratings like that: Rating system http://img69.imageshack.us/img69/4241/98948761.gif The problem is
I think this is a situation every Java programmer runs into if they do
As every programmer knows tools are important and there is no tool more important
Is there a set of things that every JavaScript programmer should know to be
As a programmer I make revolutionary findings every few years. I'm either ahead of
I'm a newbie programmer working with jQuery and wonder if anyone can help me
I am a relatively new programmer so this may be a really simple question

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.