IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

C23 : un C légèrement meilleur
Le langage de programmation C continue d'évoluer, lentement et prudemment, par Daniel Lemire

Le , par Daniel Lemire

12PARTAGES

13  0 
Le langage de programmation C est l'un des langages de programmation les plus connus et les plus populaires. Il est relativement facile à apprendre et très pratique.

Il est peut-être surprenant de constater que le langage de programmation C continue d'évoluer, lentement et prudemment. Si vous avez GCC 13 ou LLVM (Clang) 16, vous disposez déjà d'un compilateur doté de certaines des fonctionnalités de la dernière norme (C23).

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 
// Only include stdio.h if it exists
#if __has_include (<stdio.h>)
  #include <stdio.h>
#endif
 
#include <stdlib.h>
 
[[deprecated]]
void f() {}
 
[[nodiscard]]
int g(int x) {
  return x + 1;
}
 
int main() {
  f(); // compile-time warning: 'f' is deprecated
  g(1); // compile-time warning
  auto x = 0b1111;
  typeof(x) y = 1'000'000; // type of y is the same as x
  printf("%d\n", x); // prints 15
  printf("%d\n", y); // prints 1000000
  constexpr int N = 10;
  // compile-time asserts using static_assert
  static_assert (N == 10, "N must be 10");
  bool a[N]; // array of N booleans
  for (int i = 0; i < N; ++i) {
    a[i] = true;
  }
  printf("%d\n", a[0]); // prints 1
}

  1. La première partie du code contient des directives de préprocesseur, qui sont des instructions permettant au compilateur de traiter le code source avant de le compiler. La directive #if vérifie une condition au moment de la compilation et n'inclut le code suivant que si la condition est vraie. La macro __has_include est une fonctionnalité du C++17 adoptée par le C23 qui vérifie si un fichier d'en-tête existe et peut être inclus. Dans le cas présent, elle n'est pas utile car nous savons que stdio.h est présent, mais dans d'autres cas, elle peut s'avérer utile pour déterminer quels sont les en-têtes disponibles.
  2. La partie suivante du code définit deux fonctions avec des attributs, qui sont des annotations fournissant des informations supplémentaires au compilateur sur le comportement ou l'utilisation d'une fonction, d'une variable, d'un type, etc.
    • L'attribut [[deprecated]] est une fonctionnalité du C++14 adoptée par le C23 qui marque une fonction comme obsolète et décourage son utilisation. Le compilateur émettra un avertissement si la fonction est appelée ou référencée.
    • L'attribut [[nodiscard]] est une fonctionnalité du C++17 adoptée par le C23 qui indique que la valeur de retour d'une fonction ne doit pas être ignorée ou rejetée. Le compilateur émet un avertissement si la fonction est appelée à partir d'une expression à valeur rejetée.

    Dans ce cas, la fonction f est dépréciée et ne fait rien, tandis que la fonction g renvoie la valeur d'entrée plus un et ne doit pas être ignorée. Les deux premières lignes de la fonction principale appellent les fonctions f et g et déclenchent les avertissements.
  3. La troisième ligne de la fonction principale déclare une variable x avec le mot-clé auto, une fonctionnalité du C++11 qui permet au compilateur de déduire le type de la variable à partir de son initialiseur. Dans ce cas, l'initialiseur est un littéral binaire, une fonctionnalité du C++14 adoptée par le C23 qui permet d'écrire des constantes entières en notation binaire à l'aide du préfixe 0b. La valeur de x est 0b1111, ce qui équivaut à 15 en décimal.
  4. La quatrième ligne déclare une autre variable y avec l'opérateur typeof qui renvoie le type d'une expression. Dans ce cas, l'expression est x, donc le type de y est le même que celui de x. L'initialiseur de y est un séparateur de chiffres, une caractéristique du C++14 adoptée par le C23 qui permet d'insérer des guillemets simples entre les chiffres dans les littéraux numériques afin d'améliorer la lisibilité. La valeur de y est 1'000'000, ce qui équivaut à 1000000 en décimal.
  5. La septième ligne déclare une variable constante N avec le mot-clé constexpr, qui est une caractéristique du C++11 adoptée par le C23 et qui indique que la valeur de la variable peut être évaluée au moment de la compilation. La valeur de N est 10. Auparavant, on utilisait souvent une macro pour définir une constante au moment de la compilation (par exemple, #define N 10).
  6. La huitième ligne utilise le mot-clé static_assert, qui est une syntaxe du C++11 adoptée par le C23 et qui effectue une vérification d'assertion au moment de la compilation. Le mot-clé prend comme arguments une expression booléenne et un message facultatif sous forme de chaîne de caractères. Si l'expression est fausse, le compilateur émettra une erreur et arrêtera la compilation, en affichant le message. Si l'expression est vraie, le compilateur ne fera rien. Dans ce cas, l'expression est N == 10, ce qui est vrai, donc la compilation continue.
  7. La neuvième ligne déclare un tableau de N booléens nommé a. Un tableau est une collection d'éléments du même type qui sont stockés dans des emplacements de mémoire contigus. La taille du tableau doit être une expression constante pour les tableaux C standard (sinon il devient un tableau de longueur variable qui peut être moins efficace), c'est pourquoi N est déclaré avec constexpr. Nous utilisons également les mots-clés true et false qui deviennent des mots-clés standard en C23.

Le C23 comporte de nombreuses autres fonctionnalités, mais il faudra un certain temps pour que les compilateurs et les librairies système les rattrapent.

Ce que j'en pense pour l'instant :

  • L'introduction de constexpr en C va probablement aider à réduire la dépendance aux macros, ce qui est une bonne idée en général. Les macros fonctionnent bien en C, mais lorsqu'un bogue est introduit, il peut être difficile d'obtenir des messages d'erreur significatifs. Cela n'arrive pas très souvent, mais dans les grandes bases de code, cela peut être un problème.
  • Personnellement, j'utilise rarement auto et typeof dans d'autres langages, et je ne m'attends donc pas à les utiliser beaucoup en C. Dans certains cas spécifiques, cela peut cependant simplifier grandement le code. Cela va probablement aider à réduire la dépendance aux macros.
  • L'idée derrière static_assert est excellente. Vous effectuez une vérification qui n'a aucun impact sur les performances du logiciel, et qui peut même l'améliorer. C'est bon marché et cela peut permettre d'attraper de vilains bogues. Elle n'est pas nouvelle en C, mais l'adoption de la syntaxe C++ est une bonne idée.
  • La fonctionnalité __has_include peut simplifier la prise en charge de diverses bibliothèques standard et permettre de tester les bibliothèques disponibles. Par exemple, il devient facile de vérifier si la bibliothèque standard prend en charge l'AVX-512. Si un en-tête est manquant, vous pouvez faire échouer la compilation en donnant des instructions (par exemple, vous devez installer la bibliothèque X). C'est généralement une bonne idée pour les personnes qui ont besoin d'écrire du code portable sur lequel d'autres peuvent compter.
  • Je n'ai pas inclus l'introduction de char8_t dans le langage. J'ai beaucoup travaillé avec Unicode en C++ et je n'ai pas trouvé de bons cas d'utilisation pour le type char8_t jusqu'à présent : char est toujours suffisant dans mon expérience.

Source : "C23: a slightly better C" (par Daniel Lemire, professeur d'informatique à l'Université du Québec TELUQ)

Et vous ?

Quel est votre avis sur le sujet ?
Trouvez-vous que les conclusions de Daniel Lemire sont pertinentes et justifiées ?

Voir aussi :

C3 : un langage de programmation système basé sur le C, permet un accès sécurisé aux tableaux, les conteneurs de haut niveau et manipulation des chaînes de caractères

Les différentes façons de gérer les erreurs en C, le C ne dispose pas d'une seule façon claire pour gérer les erreurs

Une erreur dans cette actualité ? Signalez-nous-la !

Avatar de Aiekick
Membre extrêmement actif https://www.developpez.com
Le 19/04/2024 à 20:17
le c est un langage parfait. il fait entertainment ce pour quoi il a été concu.
0  1 
Avatar de marsupial
Expert éminent https://www.developpez.com
Le 22/04/2024 à 9:18
webassembly est dans les choux.
0  1