Comment des arguments de position tels que “1 $” fonctionnent-ils avec printf ()?

Par l’ man je trouve

  printf("%*d", width, num); 

et

  printf("%2$*1$d", width, num); 

sont équivalents.

Mais le deuxième style devrait être le même que:

  printf("%*d", num, width); 

Cependant, via les tests, il semble que l’ man raison; Pourquoi?

La partie pertinente de la spécification POSIX de printf() définit ce comportement:

Les conversions peuvent être appliquées au n ième argument après le format dans la liste des arguments, plutôt qu’au prochain argument inutilisé. Dans ce cas, le caractère de spécificateur de conversion% (voir ci-dessous) est remplacé par la séquence “% n $”, où n est un entier décimal compris dans la plage [1, {NL_ARGMAX}], donnant la position de l’argument dans l’argument. liste. Cette fonctionnalité permet de définir des chaînes de format qui sélectionnent les arguments dans un ordre adapté à des langues spécifiques (voir la section EXEMPLES).

Le format peut contenir des spécifications de conversion d’argument numérotées (c’est-à-dire “% n $” et “* m $”) ou des spécifications de conversion d’argument non numérotées (c’est-à-dire% et *), mais pas les deux. La seule exception à cette règle est que %% peut être mélangé avec le formulaire “% n $”. Les résultats du mélange des spécifications d’arguments numérotés et non numérotés dans une chaîne de format ne sont pas définis. Lorsque des spécifications d’argument numéroté sont utilisées, spécifier le nième argument nécessite que tous les arguments principaux, du premier au ( N-1 ) ème, soient spécifiés dans la chaîne de format.

Dans les chaînes de format contenant le formulaire “% n $” de spécification de conversion, les arguments numérotés de la liste d’arguments peuvent être référencés à partir de la chaîne de format autant de fois que nécessaire.

Le %n$ identifie l’argument dont la valeur doit être imprimée – argument 2 dans votre exemple.

Le *n$ identifie l’argument dont la valeur doit être traitée comme le format width – argument 1 dans votre exemple.

Ainsi, ceux qui ont écrit le manuel ont suivi la norme.


Vous discutez dans un commentaire:

2$* devrait correspondre au deuxième paramètre, tandis que 1$d devrait correspondre au premier, mais il s’avère que ce n’est pas vrai dans le cas de printf("%2$*1$d", width, num); .

Comme indiqué précédemment, la norme attache clairement les n$ parts en tant que modificateurs postfixes de % et * , plutôt qu’en tant que modificateurs de préfixe du spécificateur de conversion de format ( d dans cet exemple) et * . Votre conception putative pourrait probablement fonctionner, mais ce n’était pas la conception choisie.

Dans votre deuxième exemple:

 printf("%2$*1$d", width, num); 

Le premier numéro, 2, est associé au spécificateur de format et le second numéro, 1, au * . Si vous lisez la documentation de printf , cela est clair. Rien d’inhabituel ne se passe.

Une largeur de champ ou une précision, ou les deux, peuvent être indiquées par un astérisque ‘*’ ou un astérisque suivi d’un ou plusieurs chiffres décimaux et d’un `$ ‘au lieu d’une chaîne de chiffres.

Donc, le 1$ s’applique à l’astérisque, le premier argument est donc la largeur. Le 2$ s’applique à la spécification de format entière, le deuxième argument est donc celui dont la valeur sera imprimée.