C Standard Compatibility Checker for C89, C99, C11 and C17

This checker lists 16 reviewed C language and library features and shows whether each one is accepted by -std=c89, -std=c99, -std=c11 and -std=c17. Every feature has a runnable fixture and a probe that shows what an older standard reports, so you can see exactly why code that builds on one machine fails on another.

Matrix of reviewed C features in -std=c99, -std=c11 and -std=c17 lanes with accepted, optional, removed and rejected badges

How to use the checker

  1. Choose a standard to list only the features its -std flag accepts, or narrow the list by category.
  2. Select a feature to read what it does, the minimum flag and any portability caveat.
  3. Switch between the runnable fixture and the older-standard probe to compare representative GCC output.
  4. Load the program into the C compiler with one click, or copy it to compile locally with the shown command.

Interactive C89 vs C99 vs C11 vs C17 matrix

Filter reviewed C language features by standard or category, see which -std= flag accepts each one, then load the runnable fixture — or a probe demonstrating rejection or an implementation extension — into the compiler.

16 features reviewed

FeatureC89/C90-std=c89C99-std=c99C11-std=c11C17-std=c17
Not availableSupportedSupportedSupported
Not availableSupportedSupportedSupported
Not availableSupportedSupportedSupported
Not availableSupportedSupportedSupported
Not availableSupportedOptionalOptional
Not availableSupportedSupportedSupported
Not availableSupportedSupportedSupported
Not availableSupportedSupportedSupported
Not availableNot availableSupportedSupported
Not availableNot availableSupportedSupported
Not availableNot availableSupportedSupported
Not availableNot availableSupportedSupported
Not availableNot availableSupportedSupported
Not availableNot availableOptionalOptional
SupportedDeprecatedRemovedRemoved
Not availableNot availableNot availableSupported
Show the -std=c99 / c11 / c17 lanes diagramMatrix of reviewed C features in -std=c99, -std=c11 and -std=c17 lanes with accepted, optional, removed and rejected badges

_Generic type-generic macros

Added in C11 · minimum flag -std=c11

_Generic picks an expression at compile time from the type of its controlling argument — the basis for type-generic macros like <tgmath.h>.

#include <stdio.h>

#define TYPE_NAME(x) _Generic((x), \
    int: "int", \
    double: "double", \
    char *: "char *", \
    default: "other")

int main(void) {
    char text[] = "hi";
    printf("%s\n", TYPE_NAME(42));
    printf("%s\n", TYPE_NAME(3.14));
    printf("%s\n", TYPE_NAME(text + 0));
    return 0;
}
gcc -std=c11 -pedantic-errors -Wall -Wextra main.c -o main
$ gcc -std=c11 -pedantic-errors -Wall -Wextra main.c -o main && ./main
int
double
char *

Compiled without diagnostics · exit code 0

Representative GCC output, not a live run. Diagnostic wording, line and column numbers vary between compiler versions.

Interactive C struct Memory Alignment, Byte Padding & sizeof() Calculator

Inspect how a 64-bit C compiler (LP64 ABI) aligns struct members in memory, where internal and tail padding bytes are inserted, how #pragma pack(1) eliminates padding, and how reordering fields from largest to smallest alignment shrinks sizeof(struct).

1. Select a C struct layout preset
2. ABI Alignment vs Packed Mode
struct SensorPacket — Mixed int/char/double struct (Padding Waste)

Interleaving 1-byte char members with 4-byte int and 8-byte double members forces 10 bytes of internal alignment padding on 64-bit LP64 (24 bytes total for 14 bytes of raw data).

Optimization insight: Reordering members from largest alignment (8B double) to smallest (1B char) shrinks sizeof(struct SensorPacket) from 24 bytes to 16 bytes — saving 8 bytes (33%) per struct.

Total sizeof(struct)
24 bytes
_Alignof = 8B (LP64)
Raw Member Data
14 bytes
4 fields
Padding Bytes
10 bytes
10B internal + 0B tail
Reorder Savings (LP64)
8 bytes saved
24B -> 16B (-33%)

Visual Byte-Grid (8-Byte / 64-Bit Word Rows)

Member byteInternal paddingTail padding
+0..+70x00
+0
status
+1PAD
pad
+2PAD
pad
+3PAD
pad
+4
reading
+5
reading
+6
reading
+7
reading
+8..+150x08
+8
flags
+9PAD
pad
+10PAD
pad
+11PAD
pad
+12PAD
pad
+13PAD
pad
+14PAD
pad
+15PAD
pad
+16..+230x10
+16
timestamp
+17
timestamp
+18
timestamp
+19
timestamp
+20
timestamp
+21
timestamp
+22
timestamp
+23
timestamp

Member offsetof(), Alignment & Padding Table

Member Declarationoffsetof()Byte RangesizeofAlignPadding BeforeAction
char status;+0B0..01B1B0B
int reading;+4B4..74B4B+3B pad (1..3)
char flags;+8B8..81B1B0B
double timestamp;+16B16..238B8B+7B pad (9..15)
Runnable C11 sizeof() & offsetof() Probe
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>

struct SensorPacket {
    char status;
    int reading;
    char flags;
    double timestamp;
};

struct SensorPacketOptimal {
    double timestamp;
    int reading;
    char status;
    char flags;
};

int main(void) {
    printf("=== struct SensorPacket (64-bit LP64 ABI) ===\n");
    printf("sizeof(struct SensorPacket)   = %zu bytes\n", sizeof(struct SensorPacket));
    printf("_Alignof(struct SensorPacket) = %zu bytes\n", _Alignof(struct SensorPacket));
    printf("Raw member data sum        = 14 bytes\n");
    printf("Total padding bytes        = %zu bytes\n", sizeof(struct SensorPacket) - (size_t)14);
    printf("  offsetof(status) = %2zuB  (size: %2zuB)\n", offsetof(struct SensorPacket, status), sizeof(((struct SensorPacket *)0)->status));
    printf("  offsetof(reading) = %2zuB  (size: %2zuB)\n", offsetof(struct SensorPacket, reading), sizeof(((struct SensorPacket *)0)->reading));
    printf("  offsetof(flags) = %2zuB  (size: %2zuB)\n", offsetof(struct SensorPacket, flags), sizeof(((struct SensorPacket *)0)->flags));
    printf("  offsetof(timestamp) = %2zuB  (size: %2zuB)\n", offsetof(struct SensorPacket, timestamp), sizeof(((struct SensorPacket *)0)->timestamp));
    printf("Reordered sizeof(struct SensorPacketOptimal): %zu bytes (saves %zu bytes)\n",
           sizeof(struct SensorPacketOptimal),
           sizeof(struct SensorPacket) > sizeof(struct SensorPacketOptimal)
               ? sizeof(struct SensorPacket) - sizeof(struct SensorPacketOptimal)
               : (size_t)0);
    return 0;
}
Representative GCC Output (64-bit LP64)
$ gcc -std=c11 -Wall -Wextra main.c -o main && ./main
=== struct SensorPacket (64-bit LP64 ABI) ===
sizeof(struct SensorPacket)   = 24 bytes
_Alignof(struct SensorPacket) = 8 bytes
Raw member data sum        = 14 bytes
Total padding bytes        = 10 bytes
  offsetof(status) =  0B  (size:  1B)
  offsetof(reading) =  4B  (size:  4B)
  offsetof(flags) =  8B  (size:  1B)
  offsetof(timestamp) = 16B  (size:  8B)
Reordered sizeof(struct SensorPacketOptimal): 16 bytes (saves 8 bytes)

C standard flags at a glance

GCC and Clang accept the same -std spellings. Add -pedantic-errors so a construct the chosen standard does not allow stops the build instead of compiling as an extension.

StandardDocumentGCC/Clang flag__STDC_VERSION__Main changes
C89/C90ANSI X3.159-1989 / ISO/IEC 9899:1990-std=c89not definedANSI C / ISO C90: declarations only at the top of a block, /* */ comments only, no long long.
C99ISO/IEC 9899:1999-std=c99199901LMixed declarations, // comments, designated initializers, VLAs, inline, long long, _Bool.
C11ISO/IEC 9899:2011-std=c11201112L_Generic, _Static_assert, anonymous struct/union, _Alignas, _Noreturn, <stdatomic.h>, threads; gets() removed; VLAs optional.
C17ISO/IEC 9899:2018-std=c17201710LDefect-fix revision of C11 (also called C18): no new language features, __STDC_VERSION__ becomes 201710L.

For the reasoning behind each change, read C99 vs C11 vs C17. To check the printf and scanf conversions for a type, use the C format specifier cheat sheet.

Ready to try it? Open the online C compiler, paste a program and run it, or read the C error guides when a build fails.

Frequently asked questions

How do I compile C code with a specific C standard?

Pass -std to GCC or Clang, for example gcc -std=c11 -pedantic-errors main.c -o main. The flags -std=c89 (also c90), -std=c99, -std=c11 and -std=c17 (also c18) select ISO C; the gnu89, gnu99, gnu11 and gnu17 forms add GNU extensions. Add -pedantic-errors to turn standard violations into errors.

What does "Optional" mean in the compatibility matrix?

C11 lets an implementation omit some features. For example, variable-length arrays became optional (an implementation without them defines __STDC_NO_VLA__) and <threads.h> is optional (__STDC_NO_THREADS__). Check the macro before relying on such a feature.

Is the terminal output a live compiler run?

No. Each fixture and probe was compiled locally with GCC and its first diagnostic recorded. Wording, line and column numbers vary between compiler versions. Use the load button to run the program in the online compiler with its current settings, and compile locally with the shown command to reproduce a probe.

Which C standard does GCC use by default?

It depends on the GCC release, and the default is a GNU dialect rather than strict ISO C: GCC 5 to 10 default to gnu11, GCC 11 to 14 to gnu17, and GCC 15 to gnu23. Pass an explicit -std flag so a build behaves the same on every machine.