Recherche…


Impression de la valeur d'un pointeur sur un objet

Pour imprimer la valeur d'un pointeur sur un objet (par opposition à un pointeur de fonction), utilisez le spécificateur de conversion p . Il est défini pour imprimer uniquement les pointeurs void , donc pour imprimer la valeur d'un pointeur non void il doit être explicitement converti ("casted *") en void* .

#include <stdlib.h> /* for EXIT_SUCCESS */
#include <stdio.h>  /* for printf() */

int main(void)
{
  int i;
  int * p = &i;

  printf("The address of i is %p.\n", (void*) p);

  return EXIT_SUCCESS;
}
C99

Utiliser <inttypes.h> et uintptr_t

Une autre manière d’imprimer des pointeurs en C99 ou version ultérieure utilise le type uintptr_t et les macros de <inttypes.h> :

#include <inttypes.h> /* for uintptr_t and PRIXPTR */
#include <stdio.h>    /* for printf() */

int main(void)
{
  int  i;
  int *p = &i;

  printf("The address of i is 0x%" PRIXPTR ".\n", (uintptr_t)p);

  return 0;
}

En théorie, il pourrait ne pas y avoir de type entier pouvant contenir un pointeur converti en entier (de sorte que le type uintptr_t pourrait ne pas exister). En pratique, il existe. Les pointeurs vers les fonctions ne doivent pas nécessairement être convertibles au type uintptr_t , même si, à nouveau, ils sont le plus souvent convertibles.

Si le type uintptr_t existe, il en va de même pour le type intptr_t . Il n'est pas clair pourquoi vous voudriez jamais traiter les adresses comme des entiers signés, cependant.

K & R C89

Histoire pré-standard:

Avant C89 pendant K & R fois-C il n'y avait pas de type void* (ni en- tête <stdlib.h> , ni prototypes, et donc pas d' int main(void) notation), de sorte que le pointeur a été jeté à long unsigned int et imprimé à l' aide du lx longueur modificateur / spécificateur de conversion.

L'exemple ci-dessous est juste à titre informatif. De nos jours, ce code est invalide, ce qui pourrait très bien provoquer le fameux comportement indéfini .

#include <stdio.h> /* optional in pre-standard C - for printf() */

int main()
{
  int  i;
  int *p = &i;

  printf("The address of i is 0x%lx.\n", (long unsigned) p);

  return 0;
}

Impression de la différence des valeurs de deux pointeurs sur un objet

Soustraire les valeurs de deux pointeurs à un objet donne un entier signé * 1 . Donc, il serait imprimé en utilisant au moins le spécificateur de conversion d .

Pour vous assurer qu'il existe un type suffisamment large pour contenir une telle "différence de pointeur", puisque C99 <stddef.h> définit le type ptrdiff_t . Pour imprimer un ptrdiff_t utilisez le modificateur de longueur t .

C99
#include <stdlib.h> /* for EXIT_SUCCESS */
#include <stdio.h> /* for printf() */
#include <stddef.h> /* for ptrdiff_t */


int main(void)
{
  int a[2];
  int * p1 = &a[0], * p2 = &a[1];
  ptrdiff_t pd = p2 - p1;

  printf("p1 = %p\n", (void*) p1);
  printf("p2 = %p\n", (void*) p2);
  printf("p2 - p1 = %td\n", pd);

  return EXIT_SUCCESS;
}

Le résultat pourrait ressembler à ceci:

p1 = 0x7fff6679f430
p2 = 0x7fff6679f434
p2 - p1 = 1

Veuillez noter que la valeur résultante de la différence est mise à l'échelle en fonction de la taille du type sur lequel les pointeurs ont soustrait le point, un int ici. La taille d'un int pour cet exemple est 4.


* 1 Si les deux pointeurs à soustraire ne pointent pas sur le même objet, le comportement est indéfini.

Spécificateurs de conversion pour l'impression

Spécificateur de conversion Type d'argument La description
i , d int imprime la décimale
u unsigned int imprime la décimale
o unsigned int imprime octal
x unsigned int imprime hexadécimal, minuscule
X unsigned int imprime hexadécimal, majuscule
f double les impressions flottent avec une précision par défaut de 6, si aucune précision n'est donnée (minuscules utilisées pour les nombres spéciaux nan et inf ou infinity )
F double les impressions flottent avec une précision par défaut de 6, si aucune précision n'est donnée (majuscule utilisée pour les numéros spéciaux NAN et INF ou INFINITY )
e double les impressions flottent avec une précision par défaut de 6, si aucune précision n'est donnée, en utilisant une notation scientifique utilisant mantisse / exposant; exposant minuscule et numéros spéciaux
E double les impressions flottent avec une précision par défaut de 6, si aucune précision n'est donnée, en utilisant une notation scientifique utilisant mantisse / exposant; exposant en majuscule et numéros spéciaux
g double utilise soit f ou e [voir ci-dessous]
G double utilise soit F soit E [voir ci-dessous]
a double imprime hexadécimal, minuscule
A double imprime hexadécimal, majuscule
c carboniser imprime un caractère unique
s carboniser* imprime une chaîne de caractères jusqu'à un terminateur NUL , ou tronquée à la longueur donnée par précision, si spécifiée
p vide* imprime la void pointeur void ; un pointeur non void doit être explicitement converti ("cast") en void* ; pointeur vers un objet uniquement, pas un pointeur de fonction
% n / a imprime le caractère %
n int * écrivez le nombre d'octets imprimés jusqu'ici dans l' int pointé.

Noter que les modificateurs de longueur peuvent être appliqués à %n (par exemple, %hhn indique qu'un spécificateur de conversion n suivant s'applique à un pointeur sur un argument de caractère signed char , conformément à la norme ISO / IEC 9899: 2011, § 7.21.6.1 ¶7).

Notez que les conversions à virgule flottante appliquées aux types float et double raison de règles de promotion par défaut - §6.5.2.2 Appels de fonction, ¶7 La notation par points de suspension dans un déclarant de prototype de fonction entraîne l'arrêt de la conversion après le dernier paramètre déclaré. Les promotions d'argument par défaut sont effectuées sur les arguments de fin. ) Ainsi, les fonctions telles que printf() ne sont transmises qu’à double valeurs double , même si la variable référencée est de type float .

Avec les formats g et G , le choix entre la notation e et f (ou E et F ) est documenté dans le standard C et dans la spécification POSIX pour printf() :

Le double argument représentant un nombre à virgule flottante doit être converti dans le style f ou e (ou dans le style F ou E dans le cas d'un spécificateur de conversion G ), en fonction de la valeur convertie et de la précision. Soit P la précision si elle est égale à zéro, 6 si la précision est omise ou 1 si la précision est égale à zéro. Alors, si une conversion avec le style E aurait un exposant de X :

  • Si P> X> = -4, la conversion doit être avec le style f (ou F ) et la précision P - (X+1) .
  • Sinon, la conversion doit se faire avec le style e (ou E ) et la précision P - 1 .

Enfin, à moins que le drapeau "#" ne soit utilisé, tous les zéros à la fin seront supprimés de la partie fractionnaire du résultat et le caractère décimal sera supprimé s’il ne reste aucune partie fractionnaire.

La fonction printf ()

Accessible via y compris <stdio.h> , la fonction printf() est l’outil principal utilisé pour imprimer du texte sur la console en C.

printf("Hello world!");
// Hello world!

Les tableaux de caractères normaux et non formatés peuvent être imprimés par eux-mêmes en les plaçant directement entre les parenthèses.

printf("%d is the answer to life, the universe, and everything.", 42);
// 42 is the answer to life, the universe, and everything.

int x = 3;
char y = 'Z';
char* z = "Example";
printf("Int: %d, Char: %c, String: %s", x, y, z);
// Int: 3, Char: Z, String: Example

Vous pouvez également imprimer des nombres entiers, des nombres à virgule flottante, des caractères et autres en utilisant le caractère d'échappement % , suivi d'un caractère ou d'une séquence de caractères indiquant le format, appelé spécificateur de format .

Tous les arguments supplémentaires de la fonction printf() sont séparés par des virgules et ces arguments doivent être dans le même ordre que les spécificateurs de format. Les arguments supplémentaires sont ignorés, tandis que les arguments mal typés ou l'absence d'arguments provoquent des erreurs ou un comportement indéfini. Chaque argument peut être une valeur littérale ou une variable.

Après une exécution réussie, le nombre de caractères imprimés est renvoyé avec le type int . Sinon, un échec renvoie une valeur négative.

Modificateurs de longueur

Les normes C99 et C11 spécifient les modificateurs de longueur suivants pour printf() ; leurs significations sont:

Modificateur Modifie S'applique à
hh d, i, o, u, x ou x char , signed char ou unsigned char
h d, i, o, u, x ou x short int ou unsigned short int
l d, i, o, u, x ou x long int ou unsigned long int
l a, A, e, E, f, F, g ou G double (pour compatibilité avec scanf() ; indéfini dans C90)
ll d, i, o, u, x ou x long long int ou unsigned long long int
j d, i, o, u, x ou x intmax_t ou uintmax_t
z d, i, o, u, x ou x size_t ou le type signé correspondant ( ssize_t dans POSIX)
t d, i, o, u, x ou x ptrdiff_t ou le type d'entier non signé correspondant
L a, A, e, E, f, F, g ou G long double

Si un modificateur de longueur apparaît avec un spécificateur de conversion autre que celui spécifié ci-dessus, le comportement est indéfini.

Microsoft spécifie des modificateurs de longueur différents et ne prend pas explicitement en charge hh , j , z ou t .

Modificateur Modifie S'applique à
I32 d, i, o, x ou x __int32
I32 o, u, x ou x unsigned __int32
I64 d, i, o, x ou x __int64
I64 o, u, x ou x unsigned __int64
je d, i, o, x ou X ptrdiff_t (c'est-à-dire __int32 sur les plates-formes 32 bits, __int64 sur les plates-formes 64 bits)
je o, u, x ou x size_t (c'est-à-dire unsigned __int32 sur les plates-formes 32 bits, unsigned __int64 sur les plates-formes 64 bits)
l ou l a, A, e, E, f, g ou G long double (Dans Visual C ++, bien que long double soit un type distinct, il a la même représentation interne que le double .)
l ou w c ou c Caractère large avec les fonctions printf et wprintf . (Un wC type lc , lC , wc ou wC est synonyme de C dans les fonctions printf et c dans les fonctions wprintf .)
l ou w s, S ou Z Chaîne de caractères large avec les fonctions printf et wprintf . (Un wS type ls , lS , ws ou wS est synonyme de S dans les fonctions printf et avec s dans les fonctions wprintf .)

Notez que les spécificateurs de conversion C , S et Z et les modificateurs de longueur I , I32 , I64 et w sont des extensions Microsoft. Traiter l comme un modificateur du long double plutôt que du double est différent du standard, mais vous aurez du mal à repérer la différence à moins que le long double ait une représentation différente du double .

Drapeaux de format d'impression

Le standard C (C11 et C99) définit les indicateurs suivants pour printf() :

Drapeau Conversions Sens
- tout Le résultat de la conversion doit être justifié à gauche dans le champ. La conversion est justifiée à droite si cet indicateur n'est pas spécifié.
+ numérique signé Le résultat d'une conversion signée doit toujours commencer par un signe («+» ou «-»). La conversion ne doit commencer par un signe que si une valeur négative est convertie si cet indicateur n'est pas spécifié.
<space> numérique signé Si le premier caractère d'une conversion signée n'est pas un signe ou si une conversion signée ne génère aucun caractère, un <space> doit être préfixé au résultat. Cela signifie que si les indicateurs <space> et ' + ' apparaissent tous deux, le drapeau <space> doit être ignoré.
# tout Indique que la valeur doit être convertie en un autre formulaire. Pour o conversion, il faut augmenter la précision, si et seulement si nécessaire, pour forcer le premier chiffre du résultat à être un zéro (si la valeur et la précision sont toutes les deux 0, un seul 0 est imprimé). Pour les spécificateurs de conversion x ou X , 0x (ou 0X ) doit être précédé d'un résultat non nul. Pour a , A , e , E , f , F , g et G spécificateurs de conversion, le résultat contient toujours un caractère radix, même si aucun chiffre suivent le caractère radix. Sans ce drapeau, un caractère de base apparaît dans le résultat de ces conversions uniquement si un chiffre le suit. Pour les spécificateurs de conversion g et G , les zéros à la fin ne doivent pas être supprimés du résultat normalement. Pour les autres spécificateurs de conversion, le comportement est indéfini.
0 numérique Pour les spécificateurs de conversion d, i, o, u, x, X, a, A, e, E, f, F, g et G, les zéros en tête (à la suite de toute indication de signe ou de base) sont utilisés pour le champ width plutôt que d'effectuer un remplissage d'espace, sauf lors de la conversion d'un infini ou d'un NaN. Si les drapeaux '0' et '-' apparaissent tous les deux, le drapeau '0' est ignoré. Pour les spécificateurs de conversion d, i, o, u, x et X, si une précision est spécifiée, le drapeau '0' doit être ignoré. ⌦ Si les indicateurs '0' et <apostrophe> apparaissent tous les deux, les caractères de regroupement sont insérés avant le remplissage zéro. Pour les autres conversions, le comportement est indéfini. ⌫

Ces indicateurs sont également pris en charge par Microsoft avec les mêmes significations.

La spécification POSIX pour printf() ajoute:

Drapeau Conversions Sens
' i, d, u, f, f, g, g La partie entière du résultat d'une conversion décimale doit être formatée avec des milliers de caractères de regroupement. Pour les autres conversions, le comportement n'est pas défini. Le caractère de regroupement non monétaire est utilisé.


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow