Pourquoi les nouvelles chaînes d’option de format printf () (spécifiques à la largeur de bit) n’ont-elles pas été adoptées dans le cadre de C99?

En cherchant comment faire des chaînes de format printf() multiplates-formes en C (c’est-à-dire, en tenant compte du nombre de bits que j’attends de chaque argument entier de printf() ), j’ai parcouru cette section de l’article de Wikipedia sur printf() . L’article décrit les options non standard pouvant être passées dans les chaînes de format printf() , telles que (ce qui semble être une extension spécifique à Microsoft):

 printf("%I32d\n", my32bitInt); 

Il ajoute que:

ISO C99 inclut le fichier d’en-tête inttypes.h qui inclut un certain nombre de macros à utiliser dans le codage printf indépendant de la plate-forme.

… et répertorie ensuite un ensemble de macros qui peuvent être trouvés dans cet en-tête. En regardant le fichier d’en-tête, pour les utiliser, il faudrait écrire:

  printf("%"PRId32"\n", my32bitInt); 

Ma question est: est-ce que je manque quelque chose? Est-ce vraiment la façon standard de le faire C99? Si oui, pourquoi? (Bien que je ne sois pas surpris de ne jamais avoir vu de code qui utilise les chaînes de format de cette façon, car il semble si encombrant …)

La logique C semble impliquer que normalise les pratiques existantes:

est dérivé de l’en-tête du même nom trouvé sur plusieurs systèmes 64 bits existants.

mais le rest du texte n’écrit pas à propos de ces macros, et je ne me souviens pas qu’elles étaient une pratique existante à l’époque.

Ce qui suit n’est que spéculation, mais l’expérience de la manière dont fonctionnent les comités de normalisation nous enseigne.

Un avantage des macros C99 par rapport à la normalisation de spécificateur de format supplémentaire pour printf (à noter que C99 en a également ajouté) est la fourniture de et lorsque vous avez déjà une implémentation prenant en charge les fonctionnalités requirejses dans une implémentation spécifique. manière consiste simplement à écrire deux fichiers avec typedef et macros adéquats. Cela réduit le coût de la mise en conformité existante, du risque de rupture des programmes existants qui utilisaient les fonctionnalités spécifiques à la mise en œuvre existantes (la méthode standard n’interfère pas) et facilite le transfert des programmes conformes à la mise en œuvre qui ne les possèdent pas. en-têtes (ils peuvent être fournis par le programme). De plus, si les méthodes de mise en œuvre spécifiques variaient déjà à l’époque, cela ne favoriserait pas une mise en œuvre par rapport à une autre.

Correct, voici comment le standard C99 dit que vous devriez les utiliser. Si vous voulez un code réellement portable, conforme à la lettre à 100% aux normes, vous devez toujours imprimer un int avec "%d" et un int32_t avec "%"PRId32 .

La plupart des gens ne s’embêtent pas, cependant, car il ya très peu de cas où le non-respect serait important. Sauf si vous portez votre code sous Win16 ou DOS, vous pouvez supposer que sizeof(int32_t) <= sizeof(int) , il est donc inoffensif d’ int32_t accidentellement un int32_t tant int32_t . De même, un long long correspond à peu près universellement à 64 bits (bien qu'il ne soit pas garanti qu'il en soit ainsi), donc imprimer un int64_t long long (par exemple avec un %llx ) est également sûr.

Les types int_fast32_t , int_least32_t et autres ne sont presque jamais utilisés. Vous pouvez donc imaginer que leurs spécificateurs de format correspondants sont utilisés encore plus rarement.

Vous pouvez toujours lancer vers le haut et utiliser %jd qui est le intmax_t format intmax_t .

 printf("%jd\n", (intmax_t)(-2)); 

J’ai utilisé intmax_t pour montrer que n’importe quel intXX_t peut être utilisé, mais le transtypage en long est beaucoup mieux pour le cas int32_t , puis utilisez %ld .

Je ne peux que spéculer sur pourquoi. J’aime la réponse de AProgrammer ci-dessus, mais un aspect est négligé: qu’allez- vous append à printf en tant que modificateur de format? Il existe déjà deux manières différentes d’utiliser les nombres dans une chaîne de format printf (largeur et précision). Ajouter un troisième type de nombre pour indiquer le nombre de bits de précision dans l’argument serait génial, mais où allez-vous le mettre sans confondre les gens? Malheureusement, l’un des défauts de C est que printf n’a pas été conçu pour être extensible.

Les macros sont affreuses, mais lorsque vous devez écrire du code portable sur des plates-formes 32 bits et 64 bits, elles représentent une aubaine. Absolument sauvé mon bacon.

Je pense que la réponse à votre question est pourquoi soit

  • Personne ne pouvait penser à une meilleure façon de le faire, ou
  • Le comité de normalisation n’a pu se mettre d’accord sur quoi que ce soit qui, à son avis, était clairement meilleur.

Une autre possibilité: la compatibilité descendante. Si vous ajoutez d’autres spécificateurs de format à printf ou des options supplémentaires, il est possible qu’un spécificateur dans du code antérieur à C99 ait une chaîne de format interprétée différemment.

Avec le changement C99, vous ne modifiez pas les fonctionnalités de printf .