Sök…


Skriva ut värdet på en pekare till ett objekt

För att skriva ut värdet på en pekare till ett objekt (i motsats till en funktionspekare) använd p konverteringsspecifikationen. Det definieras för att skriva ut void -pointers bara, så att skriva ut värdet av en icke void -pointer det måste uttryckligen omvandlas ( "gjuten *") till 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

Använd <inttypes.h> och uintptr_t

Ett annat sätt att skriva ut pekare i C99 eller senare använder uintptr_t typen och makron från <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;
}

I teorin kan det inte vara ett heltal typ som kan hålla någon pekaren omvandlas till ett heltal (så typen uintptr_t kanske inte existerar). I praktiken existerar det. Pekare till funktioner behöver inte vara konvertibla till typen uintptr_t - men återigen är de ofta konvertibla.

Om uintptr_t typen finns, gör intptr_t typen det också. Det är dock inte klart varför du någonsin vill behandla adresser som signerade heltal.

K&R C89

Pre-Standard History:

Före C89 under K & R-C-tider fanns det ingen typ av void* (inte heller rubrik <stdlib.h> , inte heller prototyper, och följaktligen ingen int main(void) notation), så pekaren gjordes till long unsigned int och tryckt med lx längd modifierare / konverteringsspecifikation.

Exemplet nedan är bara för informationssyfte. För närvarande är detta ogiltig kod, vilket mycket väl kan provocera det ökända odefinierade beteendet .

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

Skriva ut skillnaden mellan värdena för två pekare till ett objekt

Att subtrahera värdena för två pekare till ett objekt resulterar i ett signerat heltal * 1 . Så det skulle skrivas ut med åtminstone d konverteringsspecifikationen.

För att se till att det finns en typ som är tillräckligt bred för att hålla en sådan "pekarskillnad", eftersom C99 <stddef.h> definierar typen ptrdiff_t . För att skriva ut en ptrdiff_t använd t längdmodifieraren.

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

Resultatet kan se ut så här:

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

Observera att det resulterande värdet på skillnaden skalas efter storleken på den typ som pekarna subtraherade pekar till, int här. Storleken på en int för detta exempel är 4.


* 1 Om de två pekarna som ska subtraheras inte pekar på samma objekt är beteendet odefinierat.

Konverteringsspecifikationer för utskrift

Konverteringsspecifikation Typ av argument Beskrivning
i , d int skriver ut decimal
u osignerad int skriver ut decimal
o osignerad int skriver ut oktal
x osignerad int skriver ut hexadecimal, små bokstäver
X osignerad int skriver ut hexadecimal, versaler
f dubbel- utskrifter flyter med en standardprecision på 6, om ingen precision ges (små bokstäver används för specialnummer nan och inf eller infinity )
F dubbel- utskrifter flyter med en standardprecision på 6, om ingen precision ges (stor bokstav används för specialnummer NAN och INF eller INFINITY )
e dubbel- utskrifter flyter med en standardprecision på 6, om ingen precision ges, med hjälp av vetenskaplig notation med mantissa / exponent; små bokstäver och specialnummer
E dubbel- utskrifter flyter med en standardprecision på 6, om ingen precision ges, med hjälp av vetenskaplig notation med mantissa / exponent; stora bokstäver och specialnummer
g dubbel- använder antingen f eller e [se nedan]
G dubbel- använder antingen F eller E [se nedan]
a dubbel- skriver ut hexadecimal, små bokstäver
A dubbel- skriver ut hexadecimal, versaler
c röding skriver ut enstaka tecken
s röding* skriver ut sträng med tecken upp till en NUL terminator, eller avkortas till längd som ges med precision, om det anges
p tomhet* skriver ut void -pointervärde; en icke- void pointer bör uttryckligen konverteras ("cast") till void* ; pekaren endast till objekt, inte en funktionspekare
% n / a skriver ut % -tecknet
n int * skriva antalet byte som skrivs ut så långt in i int pekade på.

Observera att längdmodifierare kan tillämpas på %n (t.ex. %hhn indikerar att en följande n konverteringsspecifikator gäller för en pekare på ett signed char argument , enligt ISO / IEC 9899: 2011 §7.21.6.1 ¶7).

Observera att konvertering av flytande punkt gäller för typer som float och double grund av standardpromoteringsregler - §6.5.2.2 Funktionssamtal, ¶7 Noteringen ellips i en prototyp för deklarationsfunktioner gör att konvertering av argumenttyp stannar efter den senaste deklarerade parametern. Standardargumentkampanjer utförs på efterföljande argument. ) Funktioner som printf() ges alltså bara någonsin double värden, även om den referensvariabeln är av typen float .

Med formatet g och G dokumenteras valet mellan e och f (eller E och F ) notation i C-standarden och i POSIX-specifikationen för printf() :

Det dubbla argumentet som representerar ett flytpunktsnummer ska konverteras i stilen f eller e (eller i stilen F eller E i fallet med en G konverteringsspecifikation), beroende på det konverterade värdet och precisionen. Låt P lika med precisionen om icke-noll, 6 om precisionen utelämnas, eller 1 om precisionen är noll. Om en konvertering med stil E skulle ha en exponent för X :

  • Om P> X> = -4, ska konverteringen ske med stil f (eller F ) och precision P - (X+1) .
  • Annars ska konverteringen ske med stil e (eller E ) och precision P - 1 .

Slutligen, om inte '#' -flaggan används, ska alla efterföljande nollor tas bort från resultatets bråkdel och decimalpunkttecknet tas bort om det inte finns någon bråkdel kvar.

Funktionen printf ()

Åtkomst genom att inkludera <stdio.h> , funktionen printf() är det primära verktyget som används för att skriva ut text till konsolen i C.

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

Normala, oformaterade karaktärsuppsättningar kan skrivas ut av sig själva genom att placera dem direkt mellan parenteserna.

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

Alternativt kan heltal, flytpunktsnummer, tecken och mer skrivas ut med flyktecken % , följt av ett tecken eller sekvens av tecken som anger formatet, känt som formatspecifikatorn .

Alla ytterligare argument till funktionen printf() separeras med kommatecken, och dessa argument bör vara i samma ordning som formatspecifikationerna. Ytterligare argument ignoreras, medan felaktiga argument eller brist på argument orsakar fel eller odefinierat beteende. Varje argument kan vara antingen ett bokstavligt värde eller en variabel.

Efter framgångsrik körning returneras antalet tecken som skrivs ut med typ int . Annars ger ett fel ett negativt värde.

Längdmodifierare

Standarderna C99 och C11 anger följande längdmodifierare för printf() ; deras betydelse är:

modifier modifierar Gäller för
hh d, i, o, u, x eller X char , signed char eller unsigned char
h d, i, o, u, x eller X short int eller unsigned short int
l d, i, o, u, x eller X long int eller unsigned long int
l a, A, e, E, f, F, g eller G double (för kompatibilitet med scanf() ; odefinierad i C90)
ll d, i, o, u, x eller X long long int eller unsigned long long int
j d, i, o, u, x eller X intmax_t eller uintmax_t
z d, i, o, u, x eller X size_t eller motsvarande signerad typ ( ssize_t i POSIX)
t d, i, o, u, x eller X ptrdiff_t eller motsvarande osignerad heltalstyp
L a, A, e, E, f, F, g eller G long double

Om en längdmodifierare visas med någon annan konverteringsspecifikation än som anges ovan, är beteendet odefinierat.

Microsoft anger vissa olika längdmodifierare och stöder uttryckligen inte hh , j , z eller t .

modifier modifierar Gäller för
I32 d, i, o, x eller X __int32
I32 o, u, x eller X unsigned __int32
I64 d, i, o, x eller X __int64
I64 o, u, x eller X unsigned __int64
jag d, i, o, x eller X ptrdiff_t (det vill säga __int32 på 32-bitars plattformar, __int64 på 64-bitars plattformar)
jag o, u, x eller X size_t (det vill säga unsigned __int32 på 32-bitars plattformar, unsigned __int64 på 64-bitars plattformar)
l eller L a, A, e, E, f, g eller G long double (I Visual C ++, även om long double är en distinkt typ, har den samma interna representation som double .)
l eller w c eller C Brett tecken med printf och wprintf funktioner. (En lc , lC , wc eller wC typspecifikation är synonymt med C i printf funktioner och med c i wprintf funktioner.)
l eller w s, S eller Z Sträng med bred tecken med funktioner för printf och wprintf . (En ls , lS , ws eller wS typspecifikation är synonymt med S i printf funktioner och med s i wprintf funktioner.)

Observera att konverteringsspecifikationerna för C , S och Z och I32 I , I32 , I64 och w längden är Microsoft-tillägg. Att behandla l som en modifierare för long double snarare än double skiljer sig från standarden, men du kommer att vara hårt pressad för att upptäcka skillnaden om inte long double har en annan representation än double .

Skriva ut formatflaggor

C-standarden (C11 och C99 också) definierar följande flaggor för printf() :

Flagga omvandlingar Menande
- Allt Resultatet av konverteringen ska lämnas motiverat inom fältet. Omvandlingen är rättberättigad om denna flagga inte anges.
+ signerad numerisk Resultatet av en signerad konvertering ska alltid börja med ett tecken ('+' eller '-'). Konverteringen börjar med ett tecken endast när ett negativt värde konverteras om denna flagga inte anges.
<space> signerad numerisk Om det första tecknet i en signerad konvertering inte är ett tecken eller om en signerad konvertering resulterar i inga tecken, ska ett <space> förinställas till resultatet. Detta innebär att om <space> och ' + ' flaggorna båda visas, ska <space> -flaggan ignoreras.
# Allt Anger att värdet ska konverteras till en alternativ form. För o konvertering, skall den öka precisionen, om och endast om det är nödvändigt, för att tvinga den första siffran i det resultat att vara en nolla (om värdet och precision är båda 0, är en enda 0 tryckt). För x eller X konverteringsspecifikationer ska ett icke-nollresultat ha 0x (eller 0X ) förinställt till det. För a , A , e , E , f , F , g och G omvandlingsspecifikationer ska resultatet alltid innehålla ett radixtecken, även om inga siffror följer radixtecknet. Utan denna flagga visas ett radixtecken i resultatet av dessa omvandlingar endast om en siffra följer den. För konverteringsspecifikationer för g och G ska släpnollar inte tas bort från resultatet som de normalt är. För andra konverteringsspecifikationer är beteendet odefinierat.
0 numerisk För d, i, o, u, x, X, a, A, e, E, f, F, g och G-omvandlingsspecifikationer används ledande nollor (efter någon indikation på tecken eller bas) för att padda till fältet bredd snarare än att utföra rymdpolstring, utom när du konverterar en oändlighet eller NaN. Om flaggorna '0' och '-' båda visas, ignoreras flaggan '0'. För konverteringsspecifikationerna d, i, o, u, x och X, om en precision specificeras, ska "0" -flaggan ignoreras. ⌦ Om flaggorna '0' och <apostrophe> visas båda, införs grupperingstecken innan noll stoppning. För andra konverteringar är beteendet odefinierat. ⌫

Dessa flaggor stöds också av Microsoft med samma betydelse.

POSIX-specifikationen för printf() lägger till:

Flagga omvandlingar Menande
' i, d, u, f, F, g, G Heltalsdelen av resultatet av en decimalkonvertering ska formateras med tusentals grupperingstecken. För andra konverteringar är beteendet odefinierat. Den icke-monetära grupperingstecken används.


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow