Table of Contents
ANSI C Standards (C89, C99, C11, C17 & C23): Complete Guide
If you've started learning C, you've probably run into terms like C89, C99, C11, C17, and C23. These are versions of the official C language standard — and knowing why they exist and what changed in each will make you a sharper C programmer.
What is a Programming Language Standard?
A language standard is an official specification defining syntax, keywords, data types, library functions, and compiler behavior — so the same C program behaves the same way across different compilers and machines.
Imagine if every country invented its own traffic rules. Driving from one place to another would be confusing and dangerous. C language standards work the same way. They provide a common set of rules that every compiler follows, ensuring C programs behave consistently across different systems.
Why C Needed Standards
Before standardization, the same C program could compile successfully on one compiler but fail or behave differently on another. Standards solved this portability problem.
Dennis Ritchie created C at Bell Labs in 1972, and in 1978 Kernighan and Ritchie published the unofficial spec known as K&R C. Without an official standard, compiler vendors implemented C differently — programs broke when moved between compilers, and library functions varied.
To fix this, The American National Standards Institute (ANSI) formed the X3J11 committee to standardize the C programming language., which published the first official C standard in 1989. ISO adopted almost the same spec internationally in 1990 — which is why you'll see ANSI C, C89, and C90 used interchangeably.
The first official C standard was published by ANSI in 1989. Since then, responsibility for developing new C standards has shifted to the International Organization for Standardization (ISO). Despite this, the term "ANSI C" is still widely used because of the historical significance of the C89 standard.
Timeline of C Standards
| Year | Standard | Best Known For |
|---|---|---|
| 1978 | K&R C | Unofficial language specification |
| 1989 | ANSI C (C89) | First official standard |
| 1990 | ISO C (C90) | International adoption of C89 |
| 1999 | C99 | Major language improvements |
| 2011 | C11 | Concurrency, Unicode and safety features |
| 2018 | C17 | Bug fixes and clarifications |
| 2024 | C23 | Latest major revision with modern improvements |
ANSI C (C89 / C90)
ANSI C is the first standardized version of C, published in 1989 and adopted by ISO in 1990. It gave every compiler vendor one common specification to follow — solving the portability chaos of the pre-standard era.
Major features: standard library headers
(stdio.h, stdlib.h, string.h),
function prototypes, structures/unions/enums, pointers and arrays,
preprocessor directives, and standardized syntax.
Despite being over three decades old, C89 remains widely used in embedded systems, industrial controllers, and legacy software because of its simplicity, stability, and broad compiler support. Every later C standard builds upon the foundation established by C89.
C99 Standard
Published in 1999, C99 modernized C by fixing practical annoyances of C89: mandatory upfront variable declarations, no boolean type, no runtime-sized arrays, and missing math/utility functions.
| Feature | Description |
|---|---|
| Variable Declaration Anywhere | Declare variables right where they're used, e.g. inside a for loop: for (int i = 0; ...) |
| Single-Line Comments | Added // alongside /* */ |
| Variable Length Arrays (VLA) | Array size decided at runtime: int numbers[n]; |
stdbool.h | Introduced bool (via _Bool), true, false |
long long int | 64-bit integers, e.g. long long population = 8000000000LL; |
inline Functions | Suggests inlining a function's code at the call site (compiler may ignore it) |
| Designated Initializers | Init specific struct/array members out of order: {.age = 20, .id = 101} |
| Compound Literals | Create unnamed objects inline: (int[]){10, 20, 30} |
Variable Length Arrays (VLAs) became an optional feature starting with C11, and many compilers disable them by default. If you need portable code that works across different compilers and platforms, dynamic memory allocation using malloc() is generally the safer choice.
C99 modernized C by introducing features like bool, long long, inline, Variable Length Arrays (VLAs), and designated initializers. These additions made C programs cleaner and easier to write while maintaining compatibility with most existing C89 code. Today, GCC, Clang, and modern MSVC support the majority of C99 features.
C11 Standard
Published in 2011, C11 targeted the rise of multi-core processors — focusing on concurrency, type safety, and compile-time checks rather than programmer convenience.
| Feature | Description |
|---|---|
| Multithreading | Standard thread library <threads.h> for creating/joining threads, mutexes, condition variables (support varies — GCC/Clang often lean on the platform's own threading) |
| Atomic Operations | <stdatomic.h> gives thread-safe types like atomic_int, avoiding race conditions |
| Static Assertions | _Static_assert(sizeof(int) == 4, "int must be 4 bytes"); — checked at compile time |
| Generic Selection | _Generic picks an expression based on a value's type — useful for type-generic macros |
| Alignment Support | _Alignas, _Alignof, <stdalign.h> for memory-layout optimization |
| Anonymous Structs/Unions | Nested structs/unions without names, for simpler member access |
| Unicode Support | char16_t, char32_t in <uchar.h> for UTF-16/UTF-32 |
| Optional VLAs | Variable Length Arrays became optional, not mandatory |
C11 brought C into the multi-core era by introducing standardized support for multithreading, improved safety features, and better portability. It remains one of the most widely adopted standards for system software, embedded systems, operating systems, and performance-critical applications.
C17 Standard
Published in 2018, C17 introduced no new language features. It's a pure maintenance release: fixing defects, clarifying ambiguous wording, and improving compiler consistency in C11. Code written for C11 compiles under C17 without changes.
If you already know C11, learning C17 is straightforward. C17 does not introduce major language features; it primarily fixes defects, clarifies the standard, and improves compiler consistency.
C23 Standard
Published in 2024, C23 is the latest revision, modernizing C's syntax and library while staying backward compatible.
| Feature | Description |
|---|---|
bool, true, false | Now built-in keywords — no <stdbool.h> needed |
nullptr | Dedicated null pointer constant: int *ptr = nullptr; |
constexpr | Compile-time constant declarations: constexpr int size = 100; |
| Empty Initializer | int numbers[10] = {}; zero-initializes everything |
| Binary Integer Literals | int mask = 0b10101100; |
| Digit Separators | long long population = 8'000'000'000; for readability |
| Improved Attributes | Standard attributes for better diagnostics and optimization hints |
| Library Improvements | Standardizes many previously implementation-specific behaviors |
C17 focused on stability and compiler consistency, while C23 modernizes the language with convenient additions such as nullptr, binary literals, digit separators, and constexpr. These improvements make C code cleaner, safer, and more expressive while preserving backward compatibility with existing programs.
Comparison of ANSI C Standards
| Standard | Year | Major Focus | Major Improvements |
|---|---|---|---|
| C89 (ANSI C) | 1989 | First official standard | Standard library, function prototypes, portable compiler behavior |
| C90 | 1990 | ISO adoption of C89 | International standardization, minor edits |
| C99 | 1999 | Language modernization | bool, inline, long long, VLAs, // comments, designated initializers |
| C11 | 2011 | Safety & concurrency | Threads, atomics, static assertions, generics, Unicode |
| C17 | 2018 | Maintenance release | Bug fixes, wording improvements, compiler consistency |
| C23 | 2024 | Modern improvements | nullptr, binary literals, digit separators, constexpr, empty initializers |
Compiler Support
| Compiler | C89 | C99 | C11 | C17 | C23 |
|---|---|---|---|---|---|
| GCC | ✔ | ✔ | ✔ | ✔ | ✔ Supported (Recent Versions) |
| Clang | ✔ | ✔ | ✔ | ✔ | ✔ Supported (Recent Versions) |
| MSVC | ✔ | Partial* | Mostly | Mostly | Improving |
Microsoft Visual C++ (MSVC) historically had limited support for the C99 standard. However, recent versions have significantly improved C99 compliance, making modern C development much more practical on Windows.
Most compilers allow selecting a C standard using a compiler option such as -std=c11 or -std=c23
Which C Standard Should You Learn?
| Your Goal | Recommended Standard |
|---|---|
| Learning C for the first time | C11 or C17 |
| College syllabus | C89 or C99 (depends on curriculum) |
| Competitive programming | C11 or C17 |
| Embedded systems | C99 or C11 |
| Modern software development | C17 or C23 |
| Maintaining legacy applications | C89 |
- Master the fundamentals defined by C89.
- Learn the practical improvements introduced in C99.
- Explore modern features added in C11, such as multithreading and atomics.
- Use C17 as a stable, production-ready standard.
- Discover the latest enhancements available in C23.
Conclusion
C has evolved for over five decades while keeping its core philosophy of simplicity and portability:
- C89 — first official standard
- C99 — modernized the language
- C11 — added concurrency and safety
- C17 — stabilized C11
- C23 — cleaner, modern syntax
You don't need to master every C standard separately. Build a strong foundation in core C concepts, understand the major additions introduced over time, and use a modern compiler that supports C17 or C23 whenever possible.

0 Comments