5 ms·
do you realize this would crash with empty array: #define countof(X) (sizeof(X) / sizeof((X)[0]))
by johnydepp 11y ago
do you realize this would crash with empty array:
#define countof(X) (sizeof(X) / sizeof((X)[0]))
- kayamon 11y ago1) Don't use empty arrays. 2) So add a proper version to the language which works under all cases.
- GFK_of_xmaspast 11y agoLike a std::vector ?
- jupp0r 11y agostd::array has size() without any runtime overhead.
- tines 11y agoNo, because the expression is not evaluated at any time. Only the type of the expression is used. A much better implementation would be using std::begin, std::end; #define countof(x) (end(x) - begin(x)) (except for the double evaluation, but this is better as a template function instead of a macro anyway) because it'll work on any type that supports random-access iterators which include arrays but also std::array and vector.
- hendzen 11y agoThere is such a function in the STL already. http://en.cppreference.com/w/cpp/iterator/distance http://en.cppreference.com/w/cpp/iterator/distance
- stormbrew 11y agoCorrected below, leaving here for posterity and to make sure this conversation isn't confusing in the future. The only thing I'll note is that you get a compile error on a zero length array, so the OP of this chain turns out right in a way heh. Start ignoring here: Are you suggesting end() and begin() can be called on an array? As far as I know they can't. Apparently you can deduce array length in a constexpr function now in C++11 (which I only learned just now but also couldn't get working quickly, so have some salt with that), but before that arrays always degrade to pointers when passed as function arguments so there's (afaik) no way to extract their length from their type...
- hendzen 11y agoBefore the array decays to a pointer, you can get its length. Here is the implementation of std::begin for arrays in libc++: https://github.com/llvm-mirror/libcxx/blob/60d223df071f6e3d4ffa29331ed466fff563096f/include/iterator#L1430-L1436 https://github.com/llvm-mirror/libcxx/blob/60d223df071f6e3d4...
- stormbrew 11y agoQuite right, I'm apparently rusty on my stdlib knowledge. Didn't know about the reference trick.
- onedognight 11y agoYes you can call std::begin() and std::end() on an array. int a[] = {4,5,6}; for(int i : a) ; That is how the above works.
- kayamon 11y agoDoes this work at compile-time? One of the uses for countof is (somewhat ironically) doing a enum->string table where you want to enforce the table gets manually updated properly: enum Color { red, green, blue, num_colors }; const char *color_string[] = { "red", "green", "blue" }; static_assert(countof(color_string) == num_colors);
- tines 11y agoNo, it doesn't, which is why I said this is better implemented with a template :)
- im3w1l 11y agoI tried it and it works for me (gcc 4.8.4), but I couldn't tell you why.