Hacker News new | ask | show | jobs
by Stratoscope 3461 days ago
Whether you use this method of getting the number of elements in an array or the more traditional sizeof method, please encapsulate the logic in a macro.

Instead of writing either of these:

  size_t length = sizeof array / sizeof array[0];

  size_t length = (&array)[1] - array;
Define this macro instead:

  #define countof( array )  ( sizeof(array) / sizeof((array)[0]) )
Or if you must:

  #define countof( array )  ( (&(array))[1] - (array) )
And then you can just say:

  size_t length = countof(array);
Edit: I used to call this macro 'elementsof', but it seems that 'countof' is a more common name for it and is a bit more clear too - so I'm going to run with that name in the future.
6 comments

Please don't replace a one line, obviously recognised by every C programmer since the beginning of time, sizeof(array) / sizeof (type) with some macro that not everyone knows. But alas, I've only been a C programmer for 30 years so I probably don't know what is cool these days.
A more detailed article here: http://www.g-truc.net/post-0708.html

with a cleaner way to do _countof using a template in C++ 11.

You can also use the template technique to pass a fixed size array to a function, and have the function determine the array size (without needing a 2nd length param, or null terminator element). Similar to strcpy_s(): http://stackoverflow.com/questions/23307268/how-does-strcpy-...

MSVC has a built in _countof: http://stackoverflow.com/questions/4415530/equivalents-to-ms...

Thanks for the interesting references!

While we're talking macros, anyone who reads the g-truc.net article should feel itchy after seeing the countof macro in their example:

  #define countof(arr) sizeof(arr) / sizeof(arr[0])
Two problems here:

1. The last use of 'arr' doesn't have 'arr' wrapped in parenthesis.

2. The entire expression is not wrapped in parentheses either.

If you write a macro that does any calculation like this, play it safe and put parens around every macro argument and parens around the entire expression too. Otherwise you never know what operator precedence will do to you.

Great point, about proper macro defines.

And use do/while wrappers (without a trailing semicolon) where needed: https://kernelnewbies.org/FAQ/DoWhile0

> please encapsulate the logic in a macro.

Why?

When reading such code, it means I would have to go and lookup a macro definition. So, there's a clear drawback. What's the benefit that makes it worthwhile?

Faster to read, and keeps the reader's mind at a semantically higher level.
I disagree. If you've progressed beyond the absolute beginner phase you know exactly what that line is when you see it. You've only put in work to obfuscate your code a bit and (potentially) cause conflicts with other units whose author had the same idea.
Provided that he knows about the macro. Otherwise it's slower and if you switch projects often it requires that you remember what's it about.

I guess it could be useful for teams working together on bigger codebases.

1. An appropriate named macro shouldn't cause you to need to investigate it unnecessarily

2 most IDEs allow simple hover over and see macro definition without having to break much flow.

I might go a step further and append "an appropriately implemented macro". Just because something has a good name doesn't mean it's not filled with crazy.

Otherwise I totally agree with your point.

If the macro is named appropriately, you don't have to go look up anything. And even if you do, you do it once (per project perhaps). No big deal.

I mean, you don't go look up the definitions of every function that gets called, every time they are called, right?

I doubt the author meant for this trick to be actually used, they were just showing how pointers to arrays are typed correctly in a clever way.
Indeed, one could hope that is the case! :-)

But my point with suggesting the macro applies equally to the more traditional sizeof division. I have seen code that divides the two sizeofs every time an array length is needed. I think it's better to put that calculation in a macro so you only do it in one place.

You are dividing one constant by another -- surely that would be handled at compile time?
You are correct, the compiled code will be the same whether you use a macro or not. In fact, this is true for any C macro. A macro is merely a source code text substitution done by the preprocessor. Using a macro is exactly the same as writing out the equivalent macro expansion everywhere you use it.

My suggestion to use a macro is not because of any difference in the compiled code, but to improve the readability of the source code.

While it may be optimized, I think the suggestion is that instead of using a hack repeatedly, it is arguably better to be DRY and abstract it away.
IIRC it is canonically called NELEMS(a).
I don't know if there's such a thing as "canonical" here. In MSVC, it's _countof (and it's in one of the standard headers).
Why a macro and not a static inline function?
That's a good question! Can you share the code for that function?
How exactly do you intend to get an array from a function argument?