Handy C/C++ Preprocessor Macros
Tags: c, cpp
Published: 2024-01-02 14:42:40

---
title: Handy C/C++ Preprocessor Macros
published: true
description: A set of C/C++ preprocessor macros that are useful is most any program.
tags: #c #cpp
# cover_image: https://direct_url_to_image.jpg
# Use a ratio of 100:42 for best results.
# published_at: 2024-01-01 16:34 +0000
---

## Introduction

Programming in either C or C++ invariably requires using [preprocessor macros](https://dev.to/pauljlucas/cc-preprocessor-macros-fh5) at some point. Here’s a collection of macros I find particularly handy in most any program.  These macros work in either C or C++.

## `NAME2`

This macro concatenates two identifiers together:

```c
#define NAME2(A,B)         NAME2_HELPER(A,B)
#define NAME2_HELPER(A,B)  A ## B
```

For example, `NAME2(foo,bar)` will expand into `foobar`.

> It actually will concatenate _any_ two tokens together, but concatenation is invariably used for identifiers.
>
> The reason for `NAME2_HELPER` has been explained [previously](https://dev.to/pauljlucas/cc-preprocessor-macros-fh5) in detail.

Why is this handy? Wait and see.

## `UNIQUE_NAME`

This macro forms a “unique” name:

```c
#define UNIQUE_NAME(PREFIX)  NAME2(NAME2(PREFIX,_),__LINE__)
```

Well, unique _enough_ for most cases. Specifically, it forms a unique name _only_ for the line it’s on, for example, `UNIQUE_NAME(var)` would expand into something like `var_42`.

Why is this handy? As shown in the macros below, having a unique name allows you to use the same macro multiple times in the same scope or nested scopes and avoid [shadows](https://en.wikipedia.org/wiki/Variable_shadowing) warnings.

## `ASSERT_RUN_ONCE`

This macro will [`assert`](https://dev.to/pauljlucas/using-assert-for-less-buggy-code-4773) if it’s executed more than once:

```c
#ifndef NDEBUG
#define ASSERT_RUN_ONCE()            \
  do {                               \
    static bool UNIQUE_NAME(called); \
    assert( !UNIQUE_NAME(called) );  \
    UNIQUE_NAME(called) = true;      \
  } while (0)
#else
#define ASSERT_RUN_ONCE()  (void)0
#endif /* NDEBUG */
```

It’s for use in initialization type functions to guarantee they’re called at most once, e.g.:

```c
void conf_init( void ) {
  ASSERT_RUN_ONCE();
  // ...
}
```

It’s defined only if `NDEBUG` (the macro used with [`assert`](https://en.cppreference.com/w/c/error/assert)) is _not_ defined since it’ll work only when compiling with assertions enabled (the default).

> This implementation isn’t thread-safe.  However, it’s fine if a program doesn’t use more than one thread.  If a program does use more than one thread, a thread-safe version is possible and not that much harder, but it’s left as an exercise for the reader.

## `RUN_ONCE`

This macro will run a statement exactly once:

```c
#define RUN_ONCE                     \
  static bool UNIQUE_NAME(run_once); \
  if ( (UNIQUE_NAME(run_once) ||     \
      !(UNIQUE_NAME(run_once) = true)) ) ; else

int main( int argc, char const *argv[] ) {
  RUN_ONCE conf_init();
  // ...
```

> Usually, it’s a best-practice to enclose multiple statements between a `do` ... `while` loop; however, in this case you can’t use one and have the `else` work. Despite this, it’ll work in most cases.
>
> Similarly, this implementation isn’t thread-safe either.  Again, a thread-safe version is left as an exercise for the reader.

## `ARRAY_SIZE`

This macro will return the number of elements in a statically allocated array:

```c
#define ARRAY_SIZE(A)  (sizeof(A) / sizeof(0[A]))
```

> Yes, the syntax of `0[ARRAY]` is legal. It’s a consequence of the quirky interplay between [arrays and pointers in C](https://dev.to/pauljlucas/dynamically-allocating-2d-arrays-efficiently-and-correctly-in-c-23d0#arrays-amp-pointers-in-c). Briefly, the `a[i]` syntax to access the _ith_ element of an array `a` is just [syntactic sugar](https://en.wikipedia.org/wiki/Syntactic_sugar) for `*(a+i)`. Since addition is commutative, `*(a+i)` can be alternatively written as `*(i+a)`; that in turn can be written as `i[a]`.  In C, this has no practical use.
>
> So why use it here? In C++, however, using `0[ARRAY]` will cause trying to use `ARRAY_SIZE` on an object of a `class` for which `operator[]` has been overloaded to cause a compilation error, which is what you’d want.

While `ARRAY_SIZE` works fine, it can also be [wrongly used](https://lkml.org/lkml/2015/9/3/428) on an “array” parameter:

```c
void f( int a[] ) {  // really, int *a
  for ( size_i i = 0; i < ARRAY_SIZE(a); ++i ) // WRONG
    // ...
```

> As I’ve mentioned [previously](https://dev.to/pauljlucas/obscure-c99-array-features-3270#array-syntax-for-parameters), array parameters simply don’t exist in C (or C++): the compiler rewrites such parameters as pointers.

Some compilers warn about this. For those that don’t, can `ARRAY_SIZE` be defined such that it’ll generate an error if it’s used on a pointer?  Yes (mostly).

### `IS_ARRAY`

The first thing needed is a way to determine whether the type of `A` is actually a statically allocated array (as opposed to a pointer). C++ has [`std::is_array`](https://en.cppreference.com/w/cpp/types/is_array), but what about C?

As of C23, you can use [`typeof`](https://dev.to/pauljlucas/typeof-in-c23-55p2) along with [`_Generic`](https://dev.to/pauljlucas/generic-in-c-i48):

```c
#define IS_ARRAY(A)       \
  _Generic( &(A),         \
    typeof(*A) (*)[]: 1,  \
    default         : 0   \
  )
```

This works because if `A` is actually an array:

1. The `&(A)` yields “pointer to array of type _T_.”
2. The `A` (inside `typeof`) “decays” into a pointer to its first element yielding “pointer to _T_,” i.e., `T*`.
3. The `*A` dereferences `T*` yielding the element type _T_.
3. Finally, `T (*)[]` yields “pointer to array of type _T_” which matches 1 above and `_Generic` returns `1` (true).

If `A` isn’t an array, e.g., a pointer, then none of the above works and `_Generic` matches the `default` case and returns `0` (false).

> If you’re using a version of C prior to C23, both `gcc` and `clang` support `typeof` (or `__typeof__`) as an [extension](https://gcc.gnu.org/onlinedocs/gcc/Typeof.html).

So far, so good; but how can `IS_ARRAY` be used with `ARRAY_SIZE` such that it’ll fail to compile when given a pointer?

### `STATIC_ASSERT_EXPR`

C has [`static_assert`](https://en.cppreference.com/w/c/language/_Static_assert), but it’s more like a statement.  What’s needed is a way to use it in an expression.  The trick is to realize that `static_assert` can be used pretty much anywhere, including inside a `struct` declaration that’s an argument to `sizeof()` that makes the whole thing an expression:

```c
#define STATIC_ASSERT_EXPR(EXPR,MSG) \
  (!!sizeof( struct { static_assert( (EXPR), MSG ); char c; } ))
```

If `EXPR` is non-zero, `sizeof()` will return non-zero that `!!` will convert to `1`; if `EXPR` is zero, then you’ll get a compile-time error that the assertion failed.  (The `char c` is there just so the `struct` isn’t empty.)

### `ARRAY_SIZE` 2.0

Given all that, we can now do:

```c
#define ARRAY_SIZE(A) (     \
  sizeof(A) / sizeof(0[A])  \
  * STATIC_ASSERT_EXPR( IS_ARRAY(A), #A " must be an array" ))
```

If `A` is really an array, the `STATIC_ASSERT_EXPR` will be `1` and multiplying by 1 is innocuous. (The compiler will optimize the multiplication away.)

## `FOREACH_ARRAY_ELEMENT`

Now that we have `ARRAY_SIZE` that will work _only_ on arrays, we can use it to define a convenience macro:

```c
#define FOREACH_ARRAY_ELEMENT(TYPE,VAR,A) \
  for ( TYPE const *VAR = (A); VAR < (A) + ARRAY_SIZE(A); ++VAR )
```

that reduces the boilerplate code to iterate over all elements of a statically allocated array.

## `STRLITLEN`

Now that we have `ARRAY_SIZE` that will work _only_ on arrays, we can use it to define:

```c
#define STRLITLEN(S)  (ARRAY_SIZE(S) - 1)
```

that gets the length of a C string literal (an array of `char`) at compile-time.

## Conclusion

I hope you’ll agree that these macros are handy. Feel free to use them in your programs.

## Further Reading

Here are other articles I’ve written that involve preprocessor macros:

+ [Bit Constant Macros in C](https://dev.to/pauljlucas/bit-constant-macros-in-c-42n9)
+ [C++ New Style Casts in C (sort of)](https://dev.to/pauljlucas/c-new-style-casts-in-c-sort-of-1amd)
+ [setjmp(), longjmp(), and Exception Handling in C](https://dev.to/pauljlucas/setjmp-longjmp-and-exception-handling-in-c-1h7h)