C standard versions - MarekBykowski/readme GitHub Wiki
| Standard | Year | Also known as | Key additions |
|---|---|---|---|
| C89 | 1989 | ANSI C, C90 | original standard, K&R formalised |
| C99 | 1999 | ISO C99 |
stdint.h, stdbool.h, inline, // comments, designated initialisers, VLAs, flexible array members |
| C11 | 2011 | ISO C11 |
_Static_assert, _Alignas/_Alignof, <stdatomic.h>, anonymous structs/unions, _Generic
|
| C17 | 2018 | C17, C18 | bug fixes only — no new features |
| C23 | 2023 | ISO C23 |
constexpr, typeof, nullptr, #embed, bit utilities (<stdbit.h>) |
#include <stdint.h> // uint8_t, uint32_t, int64_t etc.
#include <stdbool.h> // bool, true, false
#include <inttypes.h> // PRIu32, PRId64 format macros
// Designated initialisers
struct uart_cfg cfg = {
.baud = 115200,
.bits = 8,
.parity = false,
};
// inline functions
static inline uint32_t clamp(uint32_t v, uint32_t lo, uint32_t hi) {
return v < lo ? lo : v > hi ? hi : v;
}
// Mixed declarations and code
for (int i = 0; i < n; i++) { } // i declared in for loop
// // comments#include <stdatomic.h>
// Compile-time assertions — zero runtime cost
_Static_assert(sizeof(uint32_t) == 4, "uint32_t must be 4 bytes");
_Static_assert(BUFFER_SIZE % 64 == 0, "must be cache-line aligned");
// Explicit alignment
_Alignas(64) uint8_t dma_buf[4096]; // cache-line aligned
size_t a = _Alignof(double); // query alignment
// Atomics
atomic_int counter = ATOMIC_VAR_INIT(0);
atomic_fetch_add(&counter, 1);
int v = atomic_load_explicit(&counter, memory_order_acquire);
// Anonymous structs/unions
typedef union {
uint32_t word;
struct {
uint8_t b0, b1, b2, b3; // anonymous struct
};
} reg32_t;
reg32_t r;
r.word = 0x12345678;
r.b0; // access byte directly// nullptr — unambiguous null pointer constant
int *p = nullptr;
// typeof — like GCC extension, now standard
typeof(x) y = x;
// constexpr for constants
constexpr int MAX = 100;
// #embed — include binary file directly
const uint8_t firmware[] = {
#embed "firmware.bin"
};| Project | Standard | Notes |
|---|---|---|
| Linux kernel | C11 | since kernel 5.18 (2022); heavy GCC extensions |
| U-Boot | C11 | follows kernel conventions |
| FreeRTOS | C99 | portable, minimal dependencies |
| ArduPilot | C++11/14 | C++ not C, but same era |
| PX4 | C++14/17 | C++ with modern features |
| Safety-critical (DO-178, ISO 26262) | C99 or C90 | certification requires older standards |
| Typical MCU firmware | C99 minimum, C11 preferred |
// Attribute — packed, aligned, noreturn, weak, section
__attribute__((packed))
__attribute__((aligned(64)))
__attribute__((noreturn))
__attribute__((section(".ccmram")))
// Built-ins
__builtin_expect(x, 1) // branch prediction hint
__builtin_popcount(x) // count set bits
__builtin_clz(x) // count leading zeros
__builtin_bswap32(x) // byte swap
__builtin_unreachable() // dead code hint
// typeof (pre-C23, GCC extension)
typeof(x) tmp = x;
// Compound literals
struct point p = (struct point){.x=1, .y=2};
⚠️ GCC extensions are not portable to MSVC or other compilers — use#ifdef __GNUC__guards if portability matters.
CFLAGS += -std=c99 # strict C99
CFLAGS += -std=c11 # strict C11
CFLAGS += -std=gnu11 # C11 + GCC extensions (most common for embedded)
CFLAGS += -std=gnu99 # C99 + GCC extensions
# Always add warnings
CFLAGS += -Wall -Wextra -Wpedantic💡 Most embedded projects use
-std=gnu11— gets C11 features plus GCC extensions like__attribute__andtypeofthat embedded code relies on heavily.