Zoeken…


De waarde van een aanwijzer naar een object afdrukken

Gebruik de p conversiespecificatie om de waarde van een pointer naar een object af te drukken (in tegenstelling tot een functieaanwijzer). Het is gedefinieerd om alleen void pointers af te drukken, dus om de waarde van een niet- void pointer af te drukken, moet het expliciet worden geconverteerd ("casted *") naar 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

Gebruik van <inttypes.h> en uintptr_t

Een andere manier om pointers af te drukken in C99 of hoger maakt gebruik van het type uintptr_t en de macro's van <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;
}

In theorie is er mogelijk geen type geheel getal dat elke aanwijzer kan omzetten die is omgezet in een geheel getal (dus het type uintptr_t mogelijk niet). In de praktijk bestaat het wel. Aanwijzingen voor functies hoeven niet converteerbaar te zijn naar het type uintptr_t - hoewel ze meestal weer converteerbaar zijn.

Als het type uintptr_t bestaat, bestaat ook het type intptr_t . Het is echter niet duidelijk waarom u adressen ooit als getekende gehele getallen wilt behandelen.

K&R C89

Pre-standaard geschiedenis:

Voorafgaand aan C89 was er tijdens K & R-C tijden geen type void* (noch header <stdlib.h> , noch prototypes, en dus geen int main(void) notatie), dus de aanwijzer werd gegoten naar long unsigned int en afgedrukt met behulp van de lx lengte modifier / conversie specificatie.

Het onderstaande voorbeeld dient alleen ter informatie. Tegenwoordig is dit ongeldige code, wat heel goed het beruchte ongedefinieerde gedrag kan uitlokken.

#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;
}

Het verschil van de waarden van twee aanwijzers afdrukken naar een object

Het aftrekken van de waarden van twee verwijzingen naar een object resulteert in een geheel getal met teken * 1 . Dus het zou worden afgedrukt met behulp van ten minste de d conversiespecificatie.

Om er zeker van te zijn dat er een type is dat breed genoeg is om zo'n "pointer-verschil" te bevatten, omdat C99 <stddef.h> het type ptrdiff_t definieert. Om een ptrdiff_t af te drukken, ptrdiff_t u de t lengte modifier.

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;
}

Het resultaat kan er zo uitzien:

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

Houd er rekening mee dat de resulterende waarde van het verschil wordt geschaald door de grootte van het type waarnaar de verwijzingen aftrekken, een int hier. De grootte van een int voor dit voorbeeld is 4.


* 1 Als de twee af te trekken punten niet naar hetzelfde object wijzen, is het gedrag niet gedefinieerd.

Conversiespecificaties voor afdrukken

Conversiespecificatie Type argument Beschrijving
i , d int decimaal afdrukken
u niet ondertekend int decimaal afdrukken
o niet ondertekend int drukt octaal af
x niet ondertekend int drukt hexadecimaal, kleine letters af
X niet ondertekend int print hexadecimaal, hoofdletters
f dubbele prints drijven met een standaardprecisie van 6, als er geen precisie wordt gegeven (kleine letters gebruikt voor speciale nummers nan en inf of infinity )
F dubbele prints drijven met een standaardprecisie van 6, als er geen precisie wordt gegeven (hoofdletters gebruikt voor speciale nummers NAN en INF of INFINITY )
e dubbele prints drijven met een standaardprecisie van 6, als er geen precisie wordt gegeven, met behulp van wetenschappelijke notatie met behulp van mantisse / exponent; kleine exponent en speciale nummers
E dubbele prints drijven met een standaardprecisie van 6, als er geen precisie wordt gegeven, met behulp van wetenschappelijke notatie met behulp van mantisse / exponent; hoofdletter exponent en speciale nummers
g dubbele gebruikt f of e [zie hieronder]
G dubbele gebruikt F of E [zie hieronder]
a dubbele drukt hexadecimaal, kleine letters af
A dubbele print hexadecimaal, hoofdletters
c verkolen drukt één karakter af
s char * drukt een reeks tekens af tot een NUL terminator of afgekapt tot lengte, gegeven door precisie, indien gespecificeerd
p leegte * drukt void pointerwaarde af; een niet- void pointer moet expliciet worden geconverteerd ("cast") naar void* ; alleen aanwijzer, geen functie-aanwijzer
% n / a drukt het % -teken af
n int * schrijf het aantal bytes dat tot nu toe is afgedrukt in de int gewezen.

Merk op dat %hhn kunnen worden toegepast op %n (bijv. %hhn geeft aan dat een volgende n conversiespecificatie van toepassing is op een pointer naar een signed char , volgens de ISO / IEC 9899: 2011 §7.21.6.1 ¶7).

Merk op dat de zwevende-puntconversies van toepassing zijn op typen float en double vanwege standaard promotieregels - §6.5.2.2 Functieaanroepen, ¶7 De ellipsaanduiding in een functieprototype-declarator zorgt ervoor dat de conversie van argumenttypen stopt na de laatst opgegeven parameter. De standaard argumentpromoties worden uitgevoerd op volgargumenten. ) Zo worden functies zoals printf() alleen double waarden doorgegeven, zelfs als de variabele waarnaar wordt verwezen van het type float .

Met de g en G formaten is de keuze tussen e en f (of E en F ) notatie gedocumenteerd in de C-standaard en in de POSIX-specificatie voor printf() :

Het dubbele argument dat een getal met drijvende komma vertegenwoordigt, wordt omgezet in de stijl f of e (of in de stijl F of E in het geval van een G conversiespecificatie), afhankelijk van de geconverteerde waarde en de precisie. Laat P gelijk zijn aan de precisie als deze niet nul is, 6 als de precisie wordt weggelaten of 1 als de precisie nul is. Als een conversie met stijl E dan een exponent van X zou hebben:

  • Als P> X> = -4, moet de conversie worden uitgevoerd met stijl f (of F ) en precisie P - (X+1) .
  • Anders zal de conversie met stijl e (of E ) en precisie P - 1 .

Ten slotte, tenzij de vlag '#' wordt gebruikt, worden eventuele nullen uit het fractionele deel van het resultaat verwijderd en wordt het decimaalteken verwijderd als er geen fractioneel deel overblijft.

De functie printf ()

De functie printf() is toegankelijk via <stdio.h> en is het primaire hulpmiddel dat wordt gebruikt voor het afdrukken van tekst naar de console in C.

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

Normale, niet-opgemaakte tekenreeksen kunnen zelf worden afgedrukt door ze direct tussen haakjes te plaatsen.

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

Als alternatief kunnen gehele getallen, getallen met drijvende komma, tekens en meer worden afgedrukt met behulp van het escape-teken % , gevolgd door een teken of reeks tekens die het formaat aangeven, ook wel het formaat-specificatieprogramma genoemd .

Alle aanvullende argumenten voor de functie printf() worden gescheiden door komma's en deze argumenten moeten in dezelfde volgorde staan als de opmaakspecificaties. Extra argumenten worden genegeerd, terwijl onjuist getypte argumenten of een gebrek aan argumenten fouten of ongedefinieerd gedrag veroorzaken. Elk argument kan een letterlijke waarde of een variabele zijn.

Na succesvolle uitvoering wordt het aantal afgedrukte tekens geretourneerd met type int . Anders retourneert een mislukking een negatieve waarde.

Lengte modificaties

De C99- en C11-normen specificeren de volgende lengtemodificatoren voor printf() ; hun betekenissen zijn:

wijziger modificeert Geldt voor
hh d, i, o, u, x of X char , signed char of unsigned char
h d, i, o, u, x of X short int of unsigned short int
l d, i, o, u, x of X long int of unsigned long int
l a, A, e, E, f, F, g of G double (voor compatibiliteit met scanf() ; ongedefinieerd in C90)
ll d, i, o, u, x of X long long int of unsigned long long int
j d, i, o, u, x of X intmax_t of uintmax_t
z d, i, o, u, x of X size_t of het overeenkomstige ondertekende type ( ssize_t in POSIX)
t d, i, o, u, x of X ptrdiff_t of het overeenkomstige niet-ondertekende geheel ptrdiff_t
L a, A, e, E, f, F, g of G long double

Als een lengtemodificator wordt weergegeven met een andere conversiespecificatie dan hierboven is aangegeven, is het gedrag niet gedefinieerd.

Microsoft specificeert enkele verschillende lengtemodificatoren en ondersteunt expliciet geen hh , j , z of t .

wijziger modificeert Geldt voor
I32 d, i, o, x of X __int32
I32 o, u, x of X unsigned __int32
I64 d, i, o, x of X __int64
I64 o, u, x of X unsigned __int64
ik d, i, o, x of X ptrdiff_t (dat wil zeggen __int32 op 32-bits platforms, __int64 op 64-bits platforms)
ik o, u, x of X size_t (dat wil zeggen, unsigned __int32 op 32-bits platforms, unsigned __int64 op 64-bits platforms)
l of l a, A, e, E, f, g of G long double (in Visual C ++, hoewel long double een ander type is, heeft het dezelfde interne weergave als double .)
l of w c of C Brede karakter met printf en wprintf functies. (Een lc , lC , wc of wC soort specificiteit verschaffende synoniem C in printf functies en c in wprintf functies.)
l of w s, S of Z Wide-tekenreeks met printf en wprintf functies. (Een ls , lS , ws of wS type specificator is synoniem met S in printf functies en met s in wprintf functies.)

Merk op dat de C , S en Z conversiespecificaties en de I , I32 , I64 en w lengtemodificatoren Microsoft-extensies zijn. Het behandelen van l als een modificator voor long double plaats van double is anders dan de standaard, hoewel je moeilijk het verschil zult zien tenzij long double een andere weergave heeft dan double .

Vlaggen in afdrukformaat

De C-standaard (C11 en ook C99) definieert de volgende vlaggen voor printf() :

Vlag conversies Betekenis
- allemaal Het resultaat van de conversie blijft binnen het veld gerechtvaardigd. De conversie is gerechtvaardigd als deze vlag niet is opgegeven.
+ ondertekend numeriek Het resultaat van een ondertekende conversie begint altijd met een teken ('+' of '-'). De conversie begint alleen met een teken wanneer een negatieve waarde wordt geconverteerd als deze vlag niet is opgegeven.
<space> ondertekend numeriek Als het eerste teken van een ondertekende conversie geen teken is of als een ondertekende conversie geen tekens oplevert, wordt een <space> voorafgegaan door het resultaat. Dit betekent dat als de vlaggen <space> en ' + ' beide verschijnen, de vlag <space> moet worden genegeerd.
# allemaal Geeft aan dat de waarde moet worden geconverteerd naar een alternatieve vorm. Voor o conversie verhoogt het de precisie, indien en alleen indien nodig, om het eerste cijfer van het resultaat een nul te laten zijn (als de waarde en precisie beide 0 zijn, wordt een enkele 0 afgedrukt). Voor x of X conversiespecificaties moet aan een niet- 0X 0x (of 0X ) worden toegevoegd. Voor a , A , e , E , f , F , g en G conversiespecificaties, zal het resultaat altijd een radix-teken bevatten, zelfs als er geen cijfers op het radix-teken volgen. Zonder deze vlag verschijnt een radix-teken alleen in het resultaat van deze conversies als een cijfer erop volgt. Voor g en G conversiespecificaties mogen volgnullen niet uit het resultaat worden verwijderd zoals ze normaal zijn. Voor andere conversiespecificaties is het gedrag niet gedefinieerd.
0 numerieke Voor d, i, o, u, x, X, a, A, e, E, f, F, g en G conversiespecificaties, worden voorloopnullen (na een indicatie van teken of basis) gebruikt om naar het veld te gaan breedte in plaats van het opvullen van ruimte, behalve bij het converteren van een oneindig of NaN. Als de vlaggen '0' en '-' beide verschijnen, wordt de vlag '0' genegeerd. Voor d, i, o, u, x en X conversiespecificaties, als een precisie is opgegeven, wordt de vlag '0' genegeerd. ⌦ Als de vlaggen '0' en <apostrophe> beide verschijnen, worden de groeperingstekens vóór nulvulling ingevoegd. Voor andere conversies is het gedrag niet gedefinieerd. ⌫

Deze vlaggen worden ook ondersteund door Microsoft met dezelfde betekenissen.

De POSIX-specificatie voor printf() voegt toe:

Vlag conversies Betekenis
' i, d, u, f, F, g, G Het gehele gedeelte van het resultaat van een decimale conversie wordt opgemaakt met duizenden groeperingstekens. Voor andere conversies is het gedrag niet gedefinieerd. Het niet-monetaire groeperingsteken wordt gebruikt.


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow