Compile time assertions

In software engineering it is important to fail early and loudly, when problems are detected. Meaning that your program should report problems that, if left unsolved can lead to undefined behavior, as early as possible and in a way that is visible. This makes problems easy to detect and fix as soon as possible.

The earlier you can detect a problem is at compile time, and the “loudest” is to produce a compile error. Wouldn’t it be wonderful if you where sure your program was correct if it compiled?

We are familiar with assertions that are performed at runtime, methods like assert() can validate if we have a state that we can not meaningfully recover from and prevent an program from continuing to execute.

Similarly we can perform assertions at compile time we can use _Static_assert(). This is a method added in the C11 standard, that is evaluated at compile time. The first parameter of _Static_assert is an integral constant expression. The second parameter is a constant string literal.

_Static_assert(0, "This should not happen!")

The first parameter must be an constant expression that the compiler can evaluate at compile time, so you can not use variables that will have a value during the runtime. The compiler is smart and due to optimizations can detect and calculate during compile time all constant expressions, like the length of a literal string (strlen("a fixed string")).

Validating injected build parameters

We can use that in the cases where we have build time parameters that are injected during the build process using the preprocessor (e.g. -DKey=Value), to validate these have values and we didn’t missconfigured our build. Many times these might be values that are not committed in the repository but are injected during the build from the CI, for example an secret API key.

So if you need to validate that your build command uses a specific Macro with non-empty value, simply add a C file(or Objective-C file) in your project and call _Static_assert like this:

If by mistake the Macro is not provided (or it has no value), the build will fail with an informative message, if we did not have this check then it would fail latter at runtime.