Testing for C23 Compatibility

The C23 standard is only partially implemented on a few compilers. To ensure that you can build C23 programs, you must obtain the latest compiler version from your distro’s package manager. Even then, not all the C23 capabilities may be available.

Two things are required to test for C23 compatibility.

First, the compiler standard switch, also called the flavor, must be set to C23. This switch is ‑std=nnn where nnn is the C standard to use for compiling.

All C compilers have a default configuration. For most of today’s compilers, it’s the C17 standard. To use another standard, such as C99, you must compile with the switch ‑std=c99. For C23, here is the command line format:

clang -std=c99 source.c

I’m using clang as my compiler above, though you can use gcc or whichever compiler you prefer; the switch is identical. The file source.c is built adhering to only the C99 standard. A programmer may want to assert this standard for compatibility with an older system.

The -std=c2x switch implements the C23 standard. Don’t use -std=c23 (c23 instead of c2x), which isn’t recognized — yet.

Second, you must test the C version number held in the __STDC_VERSION__ defined constant. See those double underscores? They’re used internally to flag special defined constants.

The following code outputs the __STDC_VERSION__ value and tests for C23 compatibility.

2023_12_23-Lesson.c

#include <stdio.h>

int main()
{
    printf("C version %ld\n",__STDC_VERSION__);
    if( __STDC_VERSION__ >= 202000 )
        puts("C23 features available");
    else
        puts("C23 features unavailable");

    return 0;
}

The printf() statement outputs the value of the __STDC_VERSION__ defined constant. The if test compares this value with 202000, which seems to be the current value for C23 implementation across various compilers.

Here’s a sample run when compiled under clang without the -std=c2x switch:

C version 201710
C23 features unavailable

If I use the -std=c2x switch on the regular clang compiler, I get this output:

C version 202000
C23 features available

I find this output questionable, as this same configuration is unable to build the sample code from last week’s Lesson.

Here is the output under clang-15 without the -std=c2x switch:

C version 201710
C23 features unavailable

Here is the output under clang-15 with the -std=c2x switch:

C version 201710
C23 features available

In this configuration, the C23 test program from last week’s Lesson builds with no errors.

For the purposes of moving forward, ensure that you not only have a C compiler that not only accepts the -std=c2x switch, but can build C23 code. Apparently the value of __STDC_VERSION__ isn’t reliable. I’m unaware of any other tests, other than just running C23 code to see whether it builds without any errors.

In next week’s Lesson, I cover the way C23 deals with binary integers.

2 thoughts on “Testing for C23 Compatibility

  1. Havenʼt posted in a while, but after reading through what JeanHeyd “ThePhD” Meneide, Project Editor for ISO/IEC JTC1 SC22 WG14, has posted on the matter, I have to admit that C23 does indeed look like an interesting update to the standard… guess I should pay closer attention again 😉

    Anyway, as with previous standards, the rates at which different vendors will implement all those nice features will probably differ wildly. As such, “C” programmers will most likely have to resort to the one thing theyʼve always had to resort to in these situations — preprocessor checks (as per en.cppreference.com/w/c/23, not tested though):

    #if defined(__clang__) /* LLVM / Clang Compiler? */
    #define CLANG_VER (__clang_major__*10000 + __clang_minor__*100 + __clang_patchlevel__)

    #if CLANG_VERSION >= 150000 /* ≥ 15.0? */
    #define __bool_true_false_are_defined 1
    #endif

    #elif defined(__GNUC__) /* GNU Compiler Collection? */
    #define GCC_VER (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__)

    #if GCC_VER >= 130000 /* ≥ 13.0? */
    #define __bool_true_false_are_defined 1
    #endif

    #elif defined(_MSC_VER) /* Visual C++ Compiler? */
    /*#if _MSC_FULL_VER >= … */ /* (No standards support yet.) *
    #define __bool_true_false_are_defined 0
    /*#endif*/

    #else
    #error “Unrecognized compiler, please fix me!”
    #endif

    #if !__bool_true_false_are_defined && !defined(__cplusplus)
    #include <stdbool.h>
    #endif

Leave a Reply