Back to C Programming
2026-03-306 min read

30.2 Static Assertions

Learn 30.2 Static Assertions step by step with clear examples and exercises.

Why This Matters

Static assertions are an essential tool for ensuring that C programs adhere to specific conditions during compile-time rather than runtime. By catching errors early in the development process, they help make your code more robust and reduce the likelihood of runtime errors.

In the context of C programming, static assertions are particularly useful when you want to check that the target platform supports certain type sizes or other properties that your code relies on. For example, if your code assumes that a long int is at least 8 bytes, you can use a static assertion to ensure that this condition holds true for every system where your code is compiled.

Static assertions can help prevent runtime errors and make it easier to debug your code. They are especially valuable in situations where the cost of a runtime error is high, such as in safety-critical systems or when dealing with user data.

Prerequisites

To fully understand static assertions, you should be familiar with the following:

  1. Basic C syntax and semantics
  2. Compilation process and preprocessor directives (#define, #include)
  3. Variables, constants, and data types in C
  4. Basic control structures (if-else, loops)
  5. Understanding of the sizeof operator and how it works with different data types
  6. Knowledge of common C type sizes on various platforms
  7. Familiarity with conditional compilation directives (#if, #elif, and #endif)
  8. Basic understanding of error handling and debugging techniques in C

Core Concept

Static assertions are implemented using the _Static_assert macro, which is part of the C99 standard. This macro takes two arguments: an expression that should evaluate to a constant value at compile time, and a string literal that will be used as the error message if the expression is false.

Here's an example of how you can use _Static_assert to ensure that a long int is at least 8 bytes on your target platform:

#include <stddef.h> // for size_t

// Define the error message as a macro
#define LONG_INT_ERROR_MESSAGE "long int needs to be at least 8 bytes"

int main() {
// Check that sizeof(long int) is greater than or equal to 8
_Static_assert((sizeof(long int) >= 8), LONG_INT_ERROR_MESSAGE);

// Rest of your code here...
}

In this example, we've defined a macro LONG_INT_ERROR_MESSAGE that contains the error message to be displayed if the static assertion fails. We then use _Static_assert to check that the size of long int is greater than or equal to 8 bytes. If the size of long int is less than 8 bytes on the target platform, the compiler will issue an error message based on the provided string literal.

It's worth noting that the expression passed to _Static_assert must be computable at compile time, and the error message must be a literal string. The expression can refer to the sizes of variables but cannot refer to their values. Also, the comparison operator used in the example (>=) should ideally be replaced with an equality operator (==) to ensure that the target size is exactly 8 bytes, rather than just greater than or equal to 8 bytes.

Static assertions can be placed wherever a statement or declaration is permitted, including at the top level in the file and inside the definition of a type.

Worked Example

Let's consider an example where we have a struct that contains a long int field, and we want to ensure that this field is large enough to hold a specific value without overflowing:

#include <stddef.h> // for size_t

// Define the error message as a macro
#define LONG_INT_ERROR_MESSAGE "long int needs to be at least 10 bytes"

typedef struct {
long int value;
} MyStruct;

int main() {
// Check that sizeof(MyStruct) is greater than or equal to the size of a long int and an integer
_Static_assert((sizeof(MyStruct) >= sizeof(long int) + sizeof(int)), LONG_INT_ERROR_MESSAGE);

// Rest of your code here...
}

In this example, we've defined a struct MyStruct that contains a single field of type long int. We then use a static assertion to ensure that the size of MyStruct is at least the sum of the sizes of long int and another integer (int). If the size of long int is less than 10 bytes, the compiler will issue an error message based on the provided string literal.

Common Mistakes

Here are some common mistakes to avoid when using static assertions:

1. Not checking for the correct type sizes

Make sure you're checking the right type sizes for your specific platform and use case. For example, if you're targeting a platform where long int is already at least 8 bytes, there's no need to check this condition with a static assertion.

2. Using non-constant expressions in the assertion

Remember that the expression passed to _Static_assert must be computable at compile time. If you use variables or functions that aren't constant, the compiler will issue an error.

3. Not providing a meaningful error message

The error message provided to _Static_assert should clearly explain why the assertion failed and what the expected condition was. A vague or unhelpful error message can make it difficult to diagnose and fix the issue.

4. Comparing with the wrong operator

As mentioned earlier, using an equality operator (==) instead of a comparison operator (>=) can help ensure that the target size is exactly what you expect, rather than just meeting a minimum requirement.

5. Not handling platform-specific type sizes

If your code needs to support multiple platforms with different type sizes, consider using conditional compilation directives (#if, #elif, and #endif) to handle each case separately.

6. Overuse of static assertions

While static assertions are a powerful tool for catching errors at compile-time, overusing them can lead to cluttered code and make it difficult to understand the intended behavior of your program. Use them judiciously to validate critical assumptions about your data types and platform.

Practice Questions

  1. Write static assertions to ensure that:
  • A char is at least 2 bytes on your platform
  • An array of 1000 ints can be declared without overflowing the maximum size of an array in your platform
  • A double can represent the floating-point number Pi (approximately 3.141592653589793) with at least 6 decimal digits of precision
  1. Explain why it's important to use static assertions in safety-critical systems or when dealing with user data.

FAQ

Q: Can I use _Static_assert in a header file?

A: Yes, you can use _Static_assert in a header file. However, the error message will only be displayed if the header is included in the source file where the assertion is evaluated by the compiler.

Q: Can I nest static assertions?

A: No, you cannot nest static assertions directly within each other. If you need to check multiple conditions, consider breaking them up into separate static assertions or using a combination of preprocessor directives and conditional compilation.

Q: What happens if multiple static assertions fail during compilation?

A: The compiler will issue an error message for each failed static assertion in the order they appear in the code. If you want to group related assertions, consider using comments or documentation to help others understand their intended purpose and relationship.

Q: Is there a way to disable specific static assertions during compilation?

A: Yes, you can use conditional compilation directives (#if, #elif, and #endif) to disable specific static assertions based on certain conditions, such as the target platform or configuration options.

Q: Can I use custom macros with _Static_assert?

A: Yes, you can define your own macros and use them in the expression passed to _Static_assert. This can help make your error messages more readable and easier to understand. Just remember that the macro must expand to a constant value at compile time.