Comment interpréter judicieusement cet avertissement du compilateur?

Lorsque j’ai exécuté le code de cette question , j’ai reçu cet avertissement:

warning: format '%d' expects argument of type 'int', but argument 2 has type 'long int' [-Wformat=] printf("PQ: %d, P: %d, Q: %d", (p - q), p, q); ~^ ~~~~~~~ %ld 

Pour résoudre ce problème, j’ai utilisé %ld pour imprimer la soustraction de deux pointeurs. Et le compilateur a accepté.

Heureusement, j’ai vu un commentaire d’un autre utilisateur mentionnant que %td devrait être utilisé, car le type de résultat de la soustraction est ptrdiff_t . Cette réponse confirme cette affirmation.

Maintenant, à partir du fichier d’en-tête de stddef.h de GCC , je peux voir que ces types sont équivalents dans ce cas:

 typedef __PTRDIFF_TYPE__ ptrdiff_t; #define __PTRDIFF_TYPE__ long int 

Cependant, j’allais simplement suggérer une mauvaise correction (plus ou moins) du PO, avec %ld , au lieu de %td .

Y a-t-il moyen de comprendre que les avertissements du compilateur ne suffisent pas? Ou peut-être d’avoir sagement interprété l’avertissement lui-même et ne pas simplement réagir.

Je ne pense pas que vous puissiez dire. Cela dépend de l’intention / de la prudence / de l’intelligence du rédacteur du compilateur.

Peut-être a-t-il décidé de toujours soutenir %ld%td est attendu, ou peut-être était-il tout simplement inconscient / incapable / désireux de donner un message plus détaillé / approprié. En cas de doute, votre dernier recours est la norme.

Cela ne semble pas être une construction portable et pour “orthodoxie”, vous devriez supporter les deux spécificateurs de format.

La clé ici est: ne faites aucune forme d’arithmétique dans printf en premier lieu. Séparez l’algorithme de l’interface graphique.

Un code tel que printf("%d", p - q) est très dangereux, non seulement parce que vous pouvez obtenir des types incorrects logiquement, mais également parce que C peut vous “rendre service” et modifier silencieusement les types via une promotion de type implicite. Exemples

En outre, la plupart des compilateurs ne vous avertissent pas des spécificateurs de format incorrects. C’est une chose relativement nouvelle dans l’histoire de C, car les compilateurs ne sont pas obligés de montrer un message de diagnostic ici. Ce n’est qu’un bonus de gcc.

Comment éviter les insectes? Ces fonctions sont insortingnsèquement dangereuses – c’est comme ça et tout le monde le sait. La famille de fonctions printf & scanf sont probablement les fonctions les plus nuisibles jamais écrites dans l’histoire de la programmation, en termes de coût total des bogues causés à l’humanité. Alors, que devriez-vous faire pour:

  • Évitez si possible stdio.h et éloignez-le du code de qualité de production. La portabilité n’est pas toujours plus importante que le code robuste – il est parfois préférable d’utiliser l’API de console brute. Évitez les fonctions de liste d’arguments variables en général.
  • S’il n’est pas possible d’éviter, encapsulez la partie “GUI” de stdio.h dans un fichier séparé, ce que vous devriez faire de toute façon. Ne mélangez pas impression / saisie avec des algorithmes. Faire une interface qui utilise des pointeurs.
  • Nous sums en 2018 et non en 1970: n’écrivez pas les interfaces de la console. Ouais, je sais … il y a beaucoup de vieilles merdes qui flottent et qu’il faut entretenir. Mais de nos jours, les fonctions de console devraient être principalement utilisées à des fins de débogage et pour les débutants qui apprennent le C, auquel cas la sécurité de type pourrait ne pas être un gros problème.