Live data from Hacker News

How to find size of an array in C without sizeof

arjunsreedharan.org

201–210 of 212 posts

Re: How to find size of an array in C without sizeof

#201

Earlier quoted context omitted.

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…

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…

Great point, about proper macro defines.

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

Re: How to find size of an array in C without sizeof

#202
post #191

Why do we dereference the array pointer? Wouldn't that give us the value at the address when we just want the address? Also wouldn't the subtraction just give us a number of bytes and thus we'd still need to divide by sizeof(int))?

Pointer arithmetic works element-wise, not byte-wise. So if p is a pointer, then p+1 refers to the next element after p, regardless of the size of the pointee. And so (p+1) - p is 1, again regardless of the size of the pointee. In this case, &arr is a pointer to array, and &arr + 1 would point to the next array following the first one. But we wanted to calculate the number of elements in the array, not the fact that…

Thank you.

Re: How to find size of an array in C without sizeof

#203

Earlier quoted context omitted.

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

Re: How to find size of an array in C without sizeof

#204

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))[…

Why a macro and not a static inline function?

How exactly do you intend to get an array from a function argument?

Re: How to find size of an array in C without sizeof

#205
post #147

Earlier quoted context omitted.

I would be extremely interested to hear how you found this bug. Sounds like a difficult bug to track down, and I always learn from good debugging stories.

It was pretty easy to track down: clang38 was exiting with Assertion failed: (Distance > 0 && "The distance must be non-zero"), function areStridedAccessesIndependent, file /wrkdirs/usr/ports/devel/ llvm38/work/llvm-3.8.0.src/lib/Analysis/LoopAccessAnalysis.cpp, line 1004. Looking at the file it was easy to see what was being asserted, and to see that the type was a 32-bit integer; since I knew I was dealing with hug…

Well good thing it was ReleaseWithAsserts build!

Re: How to find size of an array in C without sizeof

#206

Earlier quoted context omitted.

Not just pointer arithmetic; also pointer comparisons. One-past-the-end pointer must compare greater-than any other pointer into that array. So an implementation that could stick an array at the very end of the address space, and do wraparound for one-past-the-end so that it's represented by all bits zero, would then need to special-case that zero value when performing any pointer comparisons.

Oh, I was assuming a runtime that didn't do wraparound. If you are doing wraparound, you already have a ton of special case work you'd have to do. But yes, you'd need logic for pointer comparisons as well.

Wouldn't it be very unusual for an environment to not do wraparound? I mean, on assembler level, pointers are just integers, and pretty much everything does wraparound arithmetics on those these days.

But, so far as I can see, this case (allocating at the very end of address space) is the only one where wraparound would matter for pointers.

And what would be the other option? If it's saturation, then your one-past-the-end pointer for the array at the end of address space would compare equal to pointer to last element...

Re: How to find size of an array in C without sizeof

#207
post #197

Earlier quoted context omitted.

No, he is correct. The C and C++ standards do allow pointers past the last element of an array to be produced via a pointer to an element of said array. They also have a provision where a pointer to a nonarray value is treated as if it were a 1-element array (so you can do "int x; int* p = *x + 1"). But in this case, the value is obviously an array object, and it's not an element to another array; hence, it is not le…

No, he isn't correct. > They also have a provision where a pointer to a nonarray value is treated as if it were a 1-element array That is not what it says. Let me quote the exact words ( emphasis mine): For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element ty…

It looks like we're quoting different standards (or different versions of them). I was referring to ISO C90, which specifically says "nonarray object". I guess yours is C99 or C11?

Re: How to find size of an array in C without sizeof

#208
post #197

Earlier quoted context omitted.

No, he isn't correct. > They also have a provision where a pointer to a nonarray value is treated as if it were a 1-element array That is not what it says. Let me quote the exact words ( emphasis mine): For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element ty…

It looks like we're quoting different standards (or different versions of them). I was referring to ISO C90, which specifically says "nonarray object". I guess yours is C99 or C11?

I quoted from C99 but C11 has the same wording.

I used to prefer C89 but learned the hard way that there are quite a few "bugs" in the standard, where it is ambiguous or otherwise fails to give a clear answer. So C99 is my go-to standard these days, even though I only care for a subset of its features.

"nonarray object" definitely sounds like such a bug. I think the intent of this clause is clear: it is meant to make sure you can always pass a pointer to a single object that treats its argument as a pointer to an array element, and does pointer arithmetic on it. One of the most common construct is simply looping over an array by incrementing the pointer, and this must work without producing an overflow when the pointer points past the array, the way it's conventionally written. If it weren't for this clause, passing a pointer to a single object to be treated as an array of size 1 would break a lot of code. Going further, is the object allocated by malloc an array or a nonarray? That would then be a critical question to ascertaining the correctness of most code out there.

And I cannot think of any reason why only pointers to nonarray objects should be usable in this manner.

Re: How to find size of an array in C without sizeof

#210

Earlier quoted context omitted.

Oh, I was assuming a runtime that didn't do wraparound. If you are doing wraparound, you already have a ton of special case work you'd have to do. But yes, you'd need logic for pointer comparisons as well.

Wouldn't it be very unusual for an environment to not do wraparound? I mean, on assembler level, pointers are just integers, and pretty much everything does wraparound arithmetics on those these days. But, so far as I can see, this case (allocating at the very end of address space) is the only one where wraparound would matter for pointers. And what would be the other option? If it's saturation, then your one-past-th…

It's pretty common to have stack and heap growing from opposite address ranges towards a central address space. That makes wrap around an unimportant feature that isn't worth the trouble.

Now, runtimes are increasingly adopting address randomization, which can change the rules about this, depending on what you are doing.

Post reply on HN