C11 Standard Features
Master the C11 standard! Learn about _Generic, _Noreturn, static_assert, anonymous structs/unions, aligned_alloc, threads, and atomics introduced in C11.
Track Your Progress
Sign in to save your learning progress
What You Will Learn
- ✓Understand what C11 introduced
- ✓Use _Generic for type-generic expressions
- ✓Use static_assert for compile-time checks
- ✓Create anonymous structs and unions
- ✓Know about C11 threading and atomics
?Why Learn C11?
C11 (ISO/IEC 9899:2011) is a major update to C that added modern features like type-generic programming, compile-time assertions, threading support, and more. Most modern compilers fully support C11.
_Generic
Type-generic macros
static_assert
Compile-time checks
Threads
threads.h
Atomics
stdatomic.h
Compile with: gcc -std=c11 or clang -std=c11
01C Standards Evolution
D Timeline of C Standards
Original C
C89/ANSI C
C99
C11 ← You are here
C23
C11 Feature Summary
_Generic
Create type-overloaded macros
static_assert
Compile-time assertions
_Noreturn
Mark functions that never return
threads.h
Portable threading API
stdatomic.h
Lock-free atomic operations
Anonymous structs
Cleaner nested structures
02_Generic: Type-Generic Expressions
The Problem _Generic Solves
In C, you can't create two functions with the same name but different parameter types (like you can in C++). This means you end up with names like:
print_int(42);
print_float(3.14f);
print_string("hello");
_Generic lets you write ONE macro that automatically picks the right function based on the argument type!
_Generic lets you create macros that behave differently based on the type of the argument — similar to function overloading in C++!
1#include <stdio.h>23// Type-generic print macro4#define print_value(x) _Generic((x), \5 int: printf("%d\n", x), \6 float: printf("%f\n", x), \7 double: printf("%lf\n", x), \8 char*: printf("%s\n", x), \9 default: printf("Unknown type\n") \10)1112// Type-generic absolute value13#define abs_val(x) _Generic((x), \14 int: abs(x), \15 float: fabsf(x), \16 double: fabs(x) \17)1819int main() {20 int a = 42;21 float b = 3.14f;22 char* s = "Hello, C11!";23 24 print_value(a); // Calls printf with %d25 print_value(b); // Calls printf with %f26 print_value(s); // Calls printf with %s27 28 return 0;29}Real-World Use
_Generic is how <tgmath.h> provides type-generic math functions like sin() that works with float, double, or long double.
02static_assert: Compile-Time Checks
static_assert checks conditions at compile time. If the condition is false, compilation fails with your error message. Great for catching configuration errors!
1#include <stdio.h>2#include <assert.h> // For static_assert in C1134// Ensure int is at least 4 bytes5static_assert(sizeof(int) >= 4, "int must be at least 4 bytes");67// Ensure struct fits in cache line8struct Data {9 int id;10 double value;11 char name[32];12};13static_assert(sizeof(struct Data) <= 64, "Data too large for cache line");1415// Check array size16#define ARRAY_SIZE 10017static_assert(ARRAY_SIZE > 0 && ARRAY_SIZE <= 1000, "Invalid array size");1819int main() {20 printf("All static assertions passed!\n");21 printf("sizeof(int) = %zu\n", sizeof(int));22 printf("sizeof(Data) = %zu\n", sizeof(struct Data));23 return 0;24}Output:
sizeof(int) = 4
sizeof(Data) = 48
If Assertion Fails
Compilation stops with error: static assertion failed: "your message"
03_Noreturn: Functions That Don't Return
_Noreturn tells the compiler that a function never returns — it either terminates the program, loops forever, or throws an exception. This helps the compiler optimize and catch bugs.
1#include <stdio.h>2#include <stdlib.h>3#include <stdnoreturn.h> // For noreturn macro45// Function that never returns6noreturn void fatal_error(const char* message) {7 fprintf(stderr, "FATAL: %s\n", message);8 exit(EXIT_FAILURE);9 // No return statement needed10}1112// Alternative syntax (without header)13_Noreturn void infinite_loop(void) {14 while (1) {15 // Forever16 }17}1819int divide(int a, int b) {20 if (b == 0) {21 fatal_error("Division by zero!");22 // Compiler knows this point is never reached23 }24 return a / b;25}2627int main() {28 int result = divide(10, 2);29 printf("Result: %d\n", result);30 31 // This would cause fatal_error:32 // divide(10, 0);33 34 return 0;35}04Anonymous Structs and Unions
C11 allows anonymous structs and unions inside other structs. Members are accessed directly without an intermediate name!
1#include <stdio.h>23struct Vector3D {4 union { // Anonymous union5 struct { float x, y, z; }; // Anonymous struct6 float components[3];7 };8};910struct Variant {11 enum { INT, FLOAT, STRING } type;12 union { // Anonymous union13 int intVal;14 float floatVal;15 char strVal[32];16 };17};1819int main() {20 struct Vector3D v = { .x = 1.0f, .y = 2.0f, .z = 3.0f };21 22 // Access via named members23 printf("x=%f, y=%f, z=%f\n", v.x, v.y, v.z);24 25 // Access via array26 for (int i = 0; i < 3; i++) {27 printf("component[%d] = %f\n", i, v.components[i]);28 }29 30 struct Variant val;31 val.type = INT;32 val.intVal = 42; // Direct access!33 printf("Value: %d\n", val.intVal);34 35 return 0;36}05aligned_alloc: Aligned Memory Allocation
aligned_alloc() allocates memory with a specific alignment. Essential for SIMD (SSE/AVX) and cache optimization!
1#include <stdio.h>2#include <stdlib.h>34int main() {5 // Allocate 1024 bytes aligned to 64-byte boundary (cache line)6 void* ptr = aligned_alloc(64, 1024);7 8 if (ptr == NULL) {9 perror("aligned_alloc failed");10 return 1;11 }12 13 printf("Allocated at: %p\n", ptr);14 printf("Address mod 64 = %lu (should be 0)\n", 15 (unsigned long)ptr % 64);16 17 free(ptr); // Use regular free()18 return 0;19}Requirements
alignment must be a power of 2, and size must be a multiple of alignment.
06C11 Features Quick Reference
| Feature | Header | Description |
|---|---|---|
| _Generic | None (keyword) | Type-generic selection |
| static_assert | <assert.h> | Compile-time assertions |
| _Noreturn | <stdnoreturn.h> | Non-returning functions |
| _Alignof / _Alignas | <stdalign.h> | Alignment control |
| aligned_alloc | <stdlib.h> | Aligned memory allocation |
| threads.h | <threads.h> | Standard threading |
| stdatomic.h | <stdatomic.h> | Atomic operations |
| Anonymous unions | None (syntax) | Unnamed members |
!Code Pitfalls: Common Mistakes & What to Watch For
Copied code often generates code using C11 features without checking compiler support or using correct compiler flags.
If you search online to "use threading in C," it might use <threads.h> and thrd_create(). However, many compilers (including MSVC and older GCC versions) don't fully support C11 threads! The You might also see _Generic or _Static_assert without telling you to compile with -std=c11.
The Trap: Online sources are trained on code from various C standards and often mix features freely. They might not realize that C11's optional features (like threading and atomics) are exactly that — optional. They also forget that many production environments still use C99 or even C89 compilers.
The Reality: Always check what C standard your target environment supports. Use -std=c11 or -std=c17 explicitly. For threading, consider POSIX threads (pthreads) for better portability. Use __STDC_VERSION__ to detect the C standard at compile time.
07bCompiler Support for C11
Before using C11 features, ensure your compiler fully supports them. Here's what you need to know about C11 support in major compilers:
| Compiler | Version | C11 Support | Notes |
|---|---|---|---|
| GCC | 4.9+ | Full | threads.h optional |
| Clang | 3.1+ | Full | Excellent support |
| MSVC | VS 2019+ | Partial | No threads.h, use Windows API |
| ICC | 15.0+ | Full | Intel compiler |
Checking C11 Support
Use the predefined macro __STDC_VERSION__ to check C standard support. For C11, it should be 201112L. Check __STDC_NO_THREADS__ and__STDC_NO_ATOMICS__ for optional feature availability.
08Frequently Asked Questions
Q:How do I enable C11 features in my compiler?
A: Use the -std=c11 flag when compiling: gcc -std=c11 program.c. Most modern compilers (GCC 4.9+, Clang 3.1+) fully support C11.
Q:What are anonymous structs and unions in C11?
A: C11 allows struct/union members without names. Their members are accessed directly from the containing struct, making nested data structures cleaner. For example, struct Point { union { int x; int y; }; };lets you access p.x directly instead ofp.coords.x.
Q:What is _Noreturn and when should I use it?
A: _Noreturn (ornoreturn with <stdnoreturn.h>) tells the compiler a function never returns — like exit(), abort(), or infinite loop functions. This helps the compiler optimize and avoids warnings about missing return statements after calls to such functions.
Q:What's the difference between _Generic and function overloading?
A: C doesn't have function overloading like C++. _Generic is a macro-based solution that selects different expressions based on argument type at compile time. It's not true overloading but achieves similar results.
Q:Why use static_assert instead of regular assert?
A: static_assert catches errors at compile time, before the program runs. It's perfect for verifying assumptions about type sizes, struct layouts, and other compile-time facts that should never vary at runtime.
Q:Is C11 threading portable?
A: threads.h is optional — compilers can skip it. Many use POSIX threads (pthreads) or Windows threads instead. Check __STDC_NO_THREADS__ to see if your compiler supports C11 threads.
Q:What is _Alignas used for?
A: _Alignas(N) ensures a variable or struct member is aligned to N-byte boundaries. This is important for performance (cache alignment) and some hardware requirements (SIMD instructions). Example: _Alignas(16) float vec[4];
Q:How do I check if my compiler supports C11?
A: Check the __STDC_VERSION__ macro. For C11, it should be 201112L. Compile with-std=c11 flag. Also check optional features with__STDC_NO_THREADS__ and __STDC_NO_ATOMICS__.
Q:What are anonymous structs and unions?
A: C11 allows unnamed struct/union members inside other structs. Members are accessed directly: outer.inner_member instead ofouter.inner.member. This simplifies code when wrapping existing structures or creating variant types.
08Summary
Key C11 Features:
_Generic— Type-generic macrosstatic_assert— Compile-time checks_Noreturn— Non-returning functions- Anonymous structs/unions
aligned_alloc— Aligned memorythreads.h— Standard threadingstdatomic.h— Atomic operationsquick_exit— Fast program termination without cleanuptimespec_get— Portable high-resolution time function- Use
-std=c11to compile
09Why Upgrade to C11?
Modern Features, Better Code
C11 brings features that make code safer and more expressive. static_assert catches errors at compile time, _Generic enables type-safe macros, and the threading library provides portable concurrency. Upgrade your compiler and start benefiting from these improvements today.
Test Your Knowledge
Related Tutorials
C23 Standard Features
Explore the newest C standard! Learn about typeof, constexpr, nullptr, _BitInt, bool/true/false as keywords, [[attributes]], and other C23 improvements.
C Preprocessor Directives
Code that runs before compilation! Learn #include, #define macros, and conditional compilation with #ifdef.
Header Files in C
Deep dive into header files! Learn to create your own .h files, understand include guards, organize declarations, and follow best practices for modular code.
Have Feedback?
Found something missing or have ideas to improve this tutorial? Let us know on GitHub!