2009-03-31 7 views
5

Je regardais simplement la page de manuel pour printf et quelque chose m'est venu à l'esprit. Je me demandais s'il y avait ici des «juristes» qui pourraient répondre à une question relativement simple: -P.question sur les spécificateurs de format printf incompatibles

Ainsi, le modificateur 't' est défini comme

La conversion entière suivante correspond à un argument de ptrdiff_t.

Alors quel est censé arriver si vous combinez cela avec une conversion entier non signé? Il est clair que o, u, x et X sont tous destinés à être interprétés comme des valeurs non signées, alors que d et i sont signés. De même, il existe des versions signées/non signées pour tous les modificateurs (int/unsigned int, size_t/ssize_t, etc) sauf ptrdiff_t.

En pratique, rien ne se passe mal puisque les versions non signées de types occupent la même quantité d'espace que les versions signées. Ainsi, le droit d'octets est retiré de la pile.

donc rien de "mauvais" qui se passe, en fait, en imprime la valeur attendue pour toutes choses testées à l'exception du "INT_MIN" (en supposant que sizeof(int) == sizeof(ptrdiff_t).

printf("%tu %td\n", INT_MIN, INT_MIN); 

impressions

2147483648 -2147483648 

sur un Système 32 bits

Est-ce que le standard a une opinion à ce sujet? Je suppose que la réponse sera "un comportement non défini." Mais j'ai pensé que je demanderais;).

+0

Est-ce que cela a quoi que ce soit à faire avec C++ (au moins avant C++ 0x)? Est-ce que printf() etc va être changé en C++ 0x pour se conformer à C99? Je pense que vous devriez supprimer la balise C++. –

+0

ptrdiff_t est défini dans cstddef en C++. printf existe aussi en C++. Je ne suis pas au courant de C++ 0x changeant printf du tout. –

+0

hrmm, semble que C++ ne peut pas avoir le modificateur c99 't'. C'est suffisant. –

Répondre

3

Rien à voir ici. Le code que vous avez écrit est légal.

Juste quelques faits pour expliquer pourquoi:

  • tous les types entiers signés ont homologues non signés, avec les mêmes dimensions/exigences d'alignement
  • ptrdiff_t est prescrit pour être un type entier signé par la norme. Par conséquent, il a un jumeau non signé. (En fait, la même logique s'applique à size_t aussi bien - ssize_t est pas C, mais Posix)
  • le spécificateur de longueur t doit travailler avec d, i, o, u, x, X types
+0

quel est l'équivalent non signé valide de ptrdiff_t? – user83255

+0

Il n'a pas de nom spécial - vous pouvez seulement dire que si ptrdiff_t est "long long" alors son homologue non signé est "unsigned long long" etc. – jpalecek

+0

Le fait important que vous avez omis est que, dans les cas où la valeur tient dans les variantes signées et non signées d'un type entier, elle a la même représentation, et la norme permet explicitement de passer le type "faux" dans ce cas. n'est possible que pour des fonctions sans prototypes et fonctions variées, de toute façon). Autant que je sache, ce serait UB pour passer une valeur négative 'ptrdiff_t' quand le spécificateur de format attend un type non signé. –

Questions connexes