đ Retour au Sommaire
Le langage C, bien quâayant plus de 50 ans, continue dâĂ©voluer. En 2024, une nouvelle norme majeure a Ă©tĂ© publiĂ©e : C23 (officiellement ISO/IEC 9899:2024). Câest la premiĂšre mise Ă jour majeure depuis C11 en 2011, soit plus de 12 ans dâĂ©volution !
Dans cette section, nous allons dĂ©couvrir ce que C23 apporte de nouveau, comprendre son Ă©tat dâadoption actuel en 2025, et surtout, dĂ©terminer si vous devriez lâutiliser dĂšs maintenant ou vous concentrer sur des versions plus Ă©tablies.
đĄ Pour les dĂ©butants : Ne vous inquiĂ©tez pas si C23 vous semble avancĂ©. La plupart des projets en production utilisent encore C99 ou C11. Cette section vous donne une vue dâensemble pour que vous sachiez ce qui existe, mais vous nâavez pas besoin de tout maĂźtriser immĂ©diatement.
Avant de plonger dans C23, voici un rappel des versions du langage C :
| Année | Standard | Nom courant | Statut en 2025 |
|---|---|---|---|
| 1989 | ANSI C | C89 / C90 | Legacy, mais encore utilisé |
| 1999 | ISO C99 | C99 | TrÚs largement utilisé |
| 2011 | ISO C11 | C11 | Standard de facto en production â |
| 2018 | ISO C17 | C17 | Corrections de bugs de C11 |
| 2024 | ISO C23 | C23 | Nouvelle norme, adoption progressive đ |
đŻ Ă retenir : C11 (avec les corrections C17) est actuellement la version la plus utilisĂ©e en production. C23 est trĂšs rĂ©cent et son adoption est encore limitĂ©e en 2025.
C23 apporte plus de 50 changements et améliorations au langage. Voici les plus significatifs, classés par importance pour un débutant.
Ce que câest : Une syntaxe standardisĂ©e pour ajouter des mĂ©tadonnĂ©es au code.
Avant C23 (avec extensions GCC) :
__attribute__((deprecated)) void old_function(void);
__attribute__((noreturn)) void exit_program(void);
Avec C23 (syntaxe standard) :
[[deprecated]] void old_function(void);
[[noreturn]] void exit_program(void);
Pourquoi câest utile :
Attributs standardisés en C23 :
[[deprecated]] : Marquer du code obsolĂšte[[nodiscard]] : Le retour de fonction ne doit pas ĂȘtre ignorĂ©[[noreturn]] : La fonction ne retourne jamais[[maybe_unused]] : Peut ne pas ĂȘtre utilisĂ© (Ă©vite les warnings)[[reproducible]] : Fonction reproductible (mĂȘme input â mĂȘme output)[[unsequenced]] : Fonction pure (aucun effet de bord)Exemple pratique :
#include <stdio.h>
#include <stdlib.h>
// Indique qu'on doit vérifier la valeur de retour
[[nodiscard]] int initialize_system(void) {
// Code d'initialisation
return 0; // 0 = succĂšs
}
// Cette fonction ne retourne jamais
[[noreturn]] void fatal_error(const char *message) {
fprintf(stderr, "FATAL: %s\n", message);
exit(1);
}
int main(void) {
// Warning si on ignore le retour !
initialize_system();
return 0;
}
nullptrLe problĂšme avec NULL :
En C classique, NULL est souvent défini comme ((void *)0) ou simplement 0, ce qui peut créer des ambiguïtés.
Avant C23 :
int *ptr = NULL; // NULL est juste 0 ou (void*)0
Avec C23 :
int *ptr = nullptr; // nullptr est un véritable type pointeur null
Pourquoi câest mieux :
nullptr depuis C++11)Exemple comparatif :
// Avant C23 : NULL peut ĂȘtre 0 ou (void*)0 selon l'implĂ©mentation
#define NULL ((void*)0) // Définition courante
int *p1 = NULL; // OK
int val = NULL; // Compile sans warning sur certains compilateurs !
// Avec C23 : nullptr a son propre type (nullptr_t)
int *p2 = nullptr; // OK
// int val2 = nullptr; // Erreur de compilation ! Plus sûr.
typeof et typeof_unqualCe que câest : Obtenir le type dâune expression.
Avant C23 (extension GNU) :
__typeof__(variable) new_variable;
Avec C23 (standard) :
typeof(variable) new_variable;
typeof_unqual(variable) unqualified_variable; // Sans const/volatile
Exemple pratique :
int x = 42;
typeof(x) y = x; // y est de type int
const int a = 10;
typeof(a) b = a; // b est "const int"
typeof_unqual(a) c = a; // c est juste "int" (sans const)
Pourquoi câest utile :
Avant C23 :
int flags = 0x0F; // Hexadécimal uniquement pour les bits
Avec C23 :
int flags = 0b00001111; // Notation binaire directe !
Utilisation pratique :
// Masques de bits plus lisibles
#define FLAG_READ 0b00000001
#define FLAG_WRITE 0b00000010
#define FLAG_EXEC 0b00000100
#define FLAG_DELETE 0b00001000
int permissions = FLAG_READ | FLAG_WRITE; // 0b00000011
Bonus : Séparateurs de chiffres (aussi en C23) :
int big_number = 1'000'000; // Plus lisible que 1000000
int binary = 0b1111'0000'1010'1100; // Groupes de 4 bits
#embed pour inclure des fichiers binairesLe problĂšme avant :
Pour inclure un fichier binaire (image, fonte, firmwareâŠ) dans un programme C, il fallait le convertir en tableau C.
Avant C23 :
// Fichier généré par un outil externe
const unsigned char data[] = {
0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A,
// ... des milliers de lignes ...
};
Avec C23 :
const unsigned char logo[] = {
#embed "logo.png" // Inclus directement le fichier binaire !
};
Pourquoi câest rĂ©volutionnaire :
Cas dâusage :
constexprCe que câest : Ăvaluation Ă la compilation (introduit partiellement en C11, Ă©tendu en C23).
Exemple C23 :
constexpr int BUFFER_SIZE = 256;
constexpr int MAX_ITEMS = BUFFER_SIZE / 4; // Calculé à la compilation
int buffer[BUFFER_SIZE]; // OK, BUFFER_SIZE est une vraie constante
Différence avec const :
const int size = 100; // Constante à l'exécution
int array1[size]; // â Erreur en C standard (VLA requis)
constexpr int size_ce = 100; // Constante Ă la compilation
int array2[size_ce]; // â
OK !
Avant C23 :
#include <stdbool.h> // Nécessaire pour bool, true, false
bool is_valid = true;
Avec C23 :
// bool, true, false sont maintenant des mots-clés !
bool is_valid = true; // Plus besoin de #include <stdbool.h>
Bonus C23 : _BitInt(N)
Types entiers de taille arbitraire :
_BitInt(7) small_int = 100; // Entier sur exactement 7 bits
_BitInt(128) huge_int = 12345; // Entier sur 128 bits
Avant C23 :
void function() {
goto end;
int x = 10; // Il faut déclarer avant le label
end:
printf("Done\n");
}
Avec C23 :
void function() {
goto end;
end: // Label peut ĂȘtre directement suivi d'une accolade
int x = 10; // Déclaration aprÚs le label !
printf("Done\n");
}
auto redéfini (comme en C++)En C classique :
auto était un mot-clé inutile (stockage automatique par défaut).
En C23 :
auto peut ĂȘtre utilisĂ© pour lâinfĂ©rence de type (comme en C++) :
auto x = 42; // x est int
auto ptr = &x; // ptr est int*
auto message = "Hi"; // message est char*
â ïž Attention : Cette fonctionnalitĂ© est encore expĂ©rimentale et peut Ă©voluer.
Chaßnes littérales UTF-8 garanties :
const char8_t *str = u8"Hello, äžç"; // UTF-8 garanti
Suffixes pour size_t :
size_t size = 100uz; // 'uz' ou 'zu' pour size_t littéral
static_assert sans message :
static_assert(sizeof(int) == 4); // Message optionnel en C23
Attributs sur les types :
struct [[deprecated]] OldStruct {
int data;
};
| Compilateur | Version | Support C23 | Statut |
|---|---|---|---|
| GCC | 14.x - 15.x | ~80-90% | đĄ Partiel |
| Clang | 18.x - 19.x | ~75-85% | đĄ Partiel |
| MSVC | 2022+ | ~40-50% | đ LimitĂ© |
| ICC (Intel) | 2024+ | ~60% | đ LimitĂ© |
đ Ătat actuel : En 2025, C23 est supportĂ© partiellement par les compilateurs majeurs. Certaines fonctionnalitĂ©s marchent, dâautres pas encore.
Avec GCC :
gcc --version
gcc -std=c23 -dM -E - < /dev/null | grep __STDC_VERSION__
Avec Clang :
clang --version
clang -std=c23 -dM -E - < /dev/null | grep __STDC_VERSION__
Résultat attendu :
__STDC_VERSION__ 202311L
(202311L = valeur dĂ©finie par le standard C23, formellement publiĂ© par lâISO en octobre 2024)
â DĂ©jĂ utilisables en production :
[[deprecated]], [[nodiscard]], etc.0b... et sĂ©parateurs 'typeof et typeof_unqualstatic_assert sans messageđĄ Support partiel / expĂ©rimental :
nullptr (GCC 14+, Clang 18+)constexpr Ă©tendu#embed (support variable selon version)auto pour infĂ©rence de typeâ Pas encore largement supportĂ© :
_BitInt(N) (support limitĂ©)Apprenez dâabord C11 (ou C99) pour les raisons suivantes :
Ensuite, explorez C23 pour :
typeof)GCC 14+ ou Clang 18+ supportent C23 partiellement.
Ubuntu 24.04+ (GCC 13/14 par défaut) :
# Vérifier la version GCC
gcc --version
# Si nécessaire, installer GCC 14
sudo apt update
sudo apt install gcc-14 g++-14
# Définir GCC 14 comme défaut
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-14 100
Compiler avec C23 :
# Avec GCC
gcc -std=c23 -Wall -Wextra program.c -o program
# Avec Clang
clang -std=c23 -Wall -Wextra program.c -o program
// test_c23.c
#include <stdio.h>
// Attributs C23
[[nodiscard]] int compute(int x) {
return x * 2;
}
int main(void) {
// Constante binaire
int flags = 0b1010;
// typeof
typeof(flags) result = compute(flags);
// nullptr
int *ptr = nullptr;
printf("Result: %d\n", result);
printf("Pointer is null: %s\n", ptr == nullptr ? "yes" : "no");
return 0;
}
Compilation :
gcc -std=c23 -Wall -Wextra test_c23.c -o test_c23
./test_c23
Sortie :
Result: 20
Pointer is null: yes
[[...]], nullptr, typeof, binaires 0b, #embedPhase 1 (maintenant) : Apprenez C11
Phase 2 (aprÚs maßtrise C11) : Découvrez C23
Phase 3 (2026+) : Adoptez C23 progressivement
Ne vous stressez pas avec C23 !
Focus sur les fondamentaux : Pointeurs, allocation mémoire, structures, fichiers, processus⊠Ces concepts sont identiques en C89, C99, C11 et C23 !
Maintenant que vous connaissez C23 et son Ă©tat dâadoption, explorons :
En route vers la maĂźtrise du C moderne ! đ