countof() is the name blessed by the C Committee for ISO C2y.
Use it if available, and define it if not.
countof() will be provided by GCC 16 and Clang 21.
This is mostly a scripted change:
$ grep -rl NITEMS | xargs sed -i s/NITEMS/countof/;
Apart from the scripted changes, I've adjusted white-space alignment,
and of course the definition at "lib/sizeof.h".
Link: <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3550.pdf#subsubsection.0.6.5.4.5>
Link: <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3550.pdf#section.0.7.21>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
({ \
long addend_[] = {a, b, __VA_ARGS__}; \
\
- addslN(NITEMS(addend_), addend_); \
+ addslN(countof(addend_), addend_); \
})
{
int len;
char enc_group[GROUP_NAME_MAX_LENGTH * 2 + 1];
- char buf[NITEMS(enc_group) + 100];
+ char buf[countof(enc_group) + 100];
if (audit_fd < 0)
return;
#include "sizeof.h"
-#define READLINKNUL(link, buf) readlinknul(link, buf, NITEMS(buf))
+#define READLINKNUL(link, buf) readlinknul(link, buf, countof(buf))
ATTR_STRING(1)
* EXAMPLES
* #define must_be_array(a) must_be(is_array(a))
*
- * #define NITEMS(a) (sizeof(a) / sizeof(*(a)) + must_be_array(a))
+ * #define countof(a) (sizeof(a) / sizeof(*(a)) + must_be_array(a))
*
* int foo[42];
- * int bar[NITEMS(foo)];
+ * int bar[countof(foo)];
*/
-/*
- * SPDX-FileCopyrightText: 2022-2023, Alejandro Colomar <alx@kernel.org>
- * SPDX-License-Identifier: BSD-3-Clause
- */
+// SPDX-FileCopyrightText: 2022-2025, Alejandro Colomar <alx@kernel.org>
+// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIBMISC_SIZEOF_H_
#include <config.h>
#include <limits.h>
+#if __has_include(<stdcountof.h>)
+# include <stdcountof.h>
+#endif
#include <sys/types.h>
#include "must_be.h"
#define memberof(T, member) ((T){}.member)
#define WIDTHOF(x) (sizeof(x) * CHAR_BIT)
#define SIZEOF_ARRAY(a) (sizeof(a) + must_be_array(a))
-#define NITEMS(a) (SIZEOF_ARRAY((a)) / sizeof((a)[0]))
-#define STRLEN(s) (NITEMS("" s "") - 1)
+
+#if !defined(countof)
+# define countof(a) (SIZEOF_ARRAY((a)) / sizeof((a)[0]))
+#endif
+
+#define STRLEN(s) (countof("" s "") - 1)
#endif // include guard
#define SNPRINTF(s, fmt, ...) \
( \
- snprintf_(s, NITEMS(s), fmt __VA_OPT__(,) __VA_ARGS__) \
+ snprintf_(s, countof(s), fmt __VA_OPT__(,) __VA_ARGS__) \
)
*
* end Pointer to one after the last element of the buffer
* pointed to by `dst`. Usually, it should be calculated
- * as `dst + NITEMS(dst)`.
+ * as `dst + countof(dst)`.
*
* fmt Format string
*
*
* end Pointer to one after the last element of the buffer
* pointed to by `dst`. Usually, it should be calculated
- * as `dst + NITEMS(dst)`.
+ * as `dst + countof(dst)`.
*
* src Source string to be copied into dst.
*
#include "sizeof.h"
-#define STRNCAT(dst, src) strncat(dst, src, NITEMS(src))
+#define STRNCAT(dst, src) strncat(dst, src, countof(src))
#endif // include guard
#include "sizeof.h"
-#define STRNCPY(dst, src) strncpy(dst, src, NITEMS(dst))
+#define STRNCPY(dst, src) strncpy(dst, src, countof(dst))
#endif // include guard
* at the buffer pointed to by dst. If the destination buffer,
* isn't large enough to hold the copy, the resulting string is
* truncated. The size of the buffer is calculated internally via
- * NITEMS().
+ * countof().
*
* RETURN VALUE
* -1 If this call truncated the resulting string.
*/
-#define STRTCPY(dst, src) strtcpy(dst, src, NITEMS(dst))
+#define STRTCPY(dst, src) strtcpy(dst, src, countof(dst))
ATTR_STRING(2)
#endif
-#define STRNDUPA(s) strndupa(s, NITEMS(s))
+#define STRNDUPA(s) strndupa(s, countof(s))
#endif // include guard
// Similar to strndup(3), but ensure that 's' is an array, and exit on ENOMEM.
#define XSTRNDUP(s) \
( \
- STRNCAT(strcpy(XMALLOC(strnlen(s, NITEMS(s)) + 1, char), ""), s) \
+ STRNCAT(strcpy(XMALLOC(strnlen(s, countof(s)) + 1, char), ""), s) \
)
// string format time
-#define STRFTIME(dst, fmt, tm) strftime(dst, NITEMS(dst), fmt, tm)
+#define STRFTIME(dst, fmt, tm) strftime(dst, countof(dst), fmt, tm)
#endif // include guard
#include "string/strcpy/strtcpy.h"
-#define DAY_TO_STR(str, day) day_to_str(NITEMS(str), str, day)
+#define DAY_TO_STR(str, day) day_to_str(countof(str), str, day)
inline void day_to_str(size_t size, char buf[size], long day);
#ident "$Id$"
-#define UTX_LINESIZE NITEMS(memberof(struct utmpx, ut_line))
+#define UTX_LINESIZE countof(memberof(struct utmpx, ut_line))
/*
addr_str = host;
gai_err = getnameinfo(addrs[0].ai_addr, addrs[0].ai_addrlen,
- host, NITEMS(host), NULL, 0, NI_NUMERICHOST);
+ host, countof(host), NULL, 0, NI_NUMERICHOST);
if (gai_err != 0) {
SYSLOG ((LOG_ERR, "getnameinfo(%s): %s", string, gai_strerror(gai_err)));
addr_str = string;
static void
test_SNPRINTF_trunc(void **state)
{
- char buf[NITEMS("foo")];
+ char buf[countof("foo")];
// Test that we're not returning SIZE_MAX
assert_true(SNPRINTF(buf, "f%su", "oo") < 0);
static void
test_SNPRINTF_ok(void **state)
{
- char buf[NITEMS("foo")];
+ char buf[countof("foo")];
assert_true(SNPRINTF(buf, "%s", "foo") == strlen("foo"));
assert_true(strcmp(buf, "foo") == 0);
static void
test_STRTCPY_trunc(void **state)
{
- char buf[NITEMS("foo")];
+ char buf[countof("foo")];
// Test that we're not returning SIZE_MAX
assert_true(STRTCPY(buf, "fooo") < 0);
static void
test_STRTCPY_ok(void **state)
{
- char buf[NITEMS("foo")];
+ char buf[countof("foo")];
assert_int_equal(STRTCPY(buf, "foo"), strlen("foo"));
assert_string_equal(buf, "foo");