Suche…


Den Wert eines Zeigers auf ein Objekt drucken

Um den Wert eines Zeigers auf ein Objekt zu drucken (im Gegensatz zu einem Funktionszeiger), verwenden Sie den p Konvertierungsspezifizierer. Es ist definiert, nur void Zeiger auszudrucken. Um den Wert eines nicht void Zeigers auszudrucken, muss er explizit ("casted *") in void* konvertiert werden.

#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

Verwenden von <inttypes.h> und uintptr_t

Eine andere Möglichkeit, Zeiger in C99 oder höher zu drucken, verwendet den Typ uintptr_t und die Makros aus <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;
}

Theoretisch gibt es möglicherweise keinen Integer-Typ, der einen in eine Integer-Zahl konvertierten Zeiger enthalten kann (daher ist der Typ uintptr_t möglicherweise nicht vorhanden). In der Praxis existiert es. Zeiger auf Funktionen müssen nicht in den Typ uintptr_t konvertierbar sein - auch wenn sie meistens konvertierbar sind.

Wenn der Typ uintptr_t vorhanden ist, gilt auch der Typ intptr_t . Es ist jedoch nicht klar, warum Sie Adressen jemals als signierte Ganzzahlen behandeln möchten.

K & R C89

Vorgeschichte:

Während der K & R-C-Zeiten vor C89 gab es weder einen Typ void* (noch Header <stdlib.h> ) noch Prototypen und daher keine int main(void) Notation int main(void) Notation). Daher wurde der Zeiger in ein long unsigned int und mit der long unsigned int lx Längenmodifizierer / Konvertierungsspezifizierer.

Das folgende Beispiel dient nur zu Informationszwecken. Heutzutage handelt es sich um ungültigen Code, der das berüchtigte undefinierte Verhalten sehr wohl provozieren könnte.

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

Drucken der Differenz der Werte zweier Zeiger auf ein Objekt

Das Abziehen der Werte von zwei Zeigern auf ein Objekt führt zu einer vorzeichenbehafteten Ganzzahl * 1 . Es würde also mindestens mit dem d Konvertierungsspezifizierer gedruckt.

Um sicherzustellen, dass ein Typ breit genug ist, um eine solche "Zeigerdifferenz" aufzunehmen, da C99 <stddef.h> den Typ ptrdiff_t definiert. Um ein ptrdiff_t zu drucken, verwenden Sie den Modifikator t length.

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

Das Ergebnis könnte so aussehen:

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

Bitte beachten Sie, dass der sich ergebende Wert der Differenz durch die Größe des Typs skaliert wird, auf den der Zeiger, auf den hier subtrahiert wird, ein int Wert ist. Die Größe eines int für dieses Beispiel ist 4.


* 1 Wenn die zwei zu subtrahierenden Zeiger nicht auf dasselbe Objekt zeigen, ist das Verhalten undefiniert.

Konvertierungsspezifikationen für den Druck

Conversion Specifier Art des Arguments Beschreibung
i , d int druckt dezimal
u unsigned int druckt dezimal
o unsigned int druckt oktal
x unsigned int druckt hexadezimal und in Kleinbuchstaben
X unsigned int druckt hexadezimal in Großbuchstaben
f doppelt druckt Float mit einer Standardgenauigkeit von 6, wenn keine Genauigkeit angegeben ist (Kleinbuchstaben werden für spezielle Zahlen nan und inf oder infinity )
F doppelt druckt Float mit einer Standardgenauigkeit von 6, wenn keine Genauigkeit angegeben ist (Großbuchstaben werden für die Sondernummern NAN und INF oder INFINITY )
e doppelt druckt Float mit einer Standardgenauigkeit von 6, wenn keine Genauigkeit angegeben wird, unter Verwendung der wissenschaftlichen Notation mit Mantisse / Exponent; Exponent- und Sondernummern für Kleinbuchstaben
E doppelt druckt Float mit einer Standardgenauigkeit von 6, wenn keine Genauigkeit angegeben wird, unter Verwendung der wissenschaftlichen Notation mit Mantisse / Exponent; Exponent- und Sondernummern für Großbuchstaben
g doppelt verwendet entweder f oder e [siehe unten]
G doppelt verwendet entweder F oder E [siehe unten]
a doppelt druckt hexadezimal und in Kleinbuchstaben
A doppelt druckt hexadezimal in Großbuchstaben
c verkohlen druckt ein einzelnes Zeichen
s verkohlen* gibt eine Zeichenfolge bis zu einem NUL Terminator aus oder wird auf die durch die Genauigkeit angegebene Länge gekürzt, sofern angegeben
p Leere* druckt einen void Zeigerwert; Ein nicht void pointer sollte explizit in void* umgewandelt werden ("cast"); Zeiger nur auf Objekt, nicht Funktionszeiger
% n / a gibt das Zeichen %
n int * schreibe die Anzahl der Bytes, die bisher gedruckt wurden, in das int auf das gezeigt wird.

Beachten Sie, dass %hhn auf %n angewendet werden können (z. B. bedeutet %hhn , dass ein nachfolgender n Konvertierungsspezifizierer auf einen Zeiger auf ein signed char Argument gemäß ISO / IEC 9899: 2011 (§7.21.6.1 ¶7 angewendet wird).

Beachten Sie, dass die Fließkomma-Konvertierungen aufgrund von Standard-Promotion-Regeln für die Typen float und double gelten . Die Standardargument-Promotions werden für nachfolgende Argumente ausgeführt. ) Funktionen wie printf() werden also immer nur mit double , auch wenn die referenzierte Variable vom Typ float .

Bei den Formaten g und G ist die Wahl zwischen der Notation e und f (oder E und F ) im C-Standard und in der POSIX-Spezifikation für printf() dokumentiert:

Das Doppelargument, das eine Gleitkommazahl darstellt, wird abhängig von dem umgesetzten Wert und der Genauigkeit in den Stil f oder e (oder im Fall eines G Konvertierungsspezifizierers in F oder E ) konvertiert. Sei P gleich der Genauigkeit, falls nicht Null, 6, wenn die Genauigkeit ausgelassen wird, oder 1, wenn die Genauigkeit Null ist. Dann, wenn eine Konvertierung mit Stil E einen Exponenten von X :

  • Wenn P> X> = -4, muss die Konvertierung mit dem Stil f (oder F ) und der Genauigkeit P - (X+1) .
  • Andernfalls erfolgt die Konvertierung mit dem Stil e (oder E ) und der Genauigkeit P - 1 .

Wenn das Flag '#' nicht verwendet wird, werden abschließende Nullen aus dem gebrochenen Teil des Ergebnisses entfernt und das Dezimalzeichen wird entfernt, wenn kein verbleibender Bruchteil vorhanden ist.

Die Funktion printf ()

Die Funktion printf() ist das wichtigste Werkzeug, das zum Drucken von Text an die Konsole in C verwendet wird, indem <stdio.h> printf() wird.

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

Normale, unformatierte Zeichen-Arrays können selbst gedruckt werden, indem sie direkt zwischen den Klammern platziert werden.

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

Alternativ können ganze Zahlen, Gleitkommazahlen, Zeichen und mehr mit dem Escape-Zeichen % gedruckt werden, gefolgt von einem Zeichen oder einer Zeichenfolge, die das Format angibt (Formatbezeichner) .

Alle zusätzlichen Argumente für die Funktion printf() werden durch Kommas getrennt. Diese Argumente sollten in derselben Reihenfolge wie die Formatbezeichner stehen. Zusätzliche Argumente werden ignoriert, während falsch eingegebene Argumente oder fehlende Argumente Fehler oder undefiniertes Verhalten verursachen. Jedes Argument kann entweder ein Literalwert oder eine Variable sein.

Nach erfolgreicher Ausführung wird die Anzahl der gedruckten Zeichen mit dem Typ int . Andernfalls liefert ein Fehler einen negativen Wert.

Längenmodifikatoren

Die Standards C99 und C11 geben die folgenden Längenmodifizierer für printf() . ihre Bedeutungen sind:

Modifikator Ändert Gilt für
hh d, i, o, u, x oder X char , signed char oder unsigned char
h d, i, o, u, x oder X short int oder unsigned short int
l d, i, o, u, x oder X long int oder unsigned long int
l a, A, e, E, f, F, g oder G double (zur Kompatibilität mit scanf() ; undefiniert in C90)
ll d, i, o, u, x oder X long long int oder unsigned long long int
j d, i, o, u, x oder X intmax_t oder uintmax_t
z d, i, o, u, x oder X size_t oder der entsprechende signierte Typ ( ssize_t in POSIX)
t d, i, o, u, x oder X ptrdiff_t oder der entsprechende Integer-Typ ohne Vorzeichen
L a, A, e, E, f, F, g oder G long double

Wenn ein Längenmodifikator mit einem anderen als dem oben angegebenen Konvertierungsspezifizierer angezeigt wird, ist das Verhalten undefiniert.

Microsoft gibt einige andere Längenmodifizierer an und unterstützt hh , j , z oder t nicht explizit.

Modifikator Ändert Gilt für
I32 d, i, o, x oder X __int32
I32 o, u, x oder X unsigned __int32
I64 d, i, o, x oder X __int64
I64 o, u, x oder X unsigned __int64
ich d, i, o, x oder X ptrdiff_t ( __int32 auf 32-Bit-Plattformen, __int64 auf 64-Bit-Plattformen)
ich o, u, x oder X size_t ( unsigned __int32 auf 32-Bit-Plattformen unsigned __int64 auf 64-Bit-Plattformen unsigned __int64 )
l oder l a, A, e, E, f, g oder G long double (In Visual C ++ ist, obwohl long double ein eindeutiger Typ ist, er dieselbe interne Darstellung wie double .)
l oder w c oder c Breites Zeichen mit Funktionen printf und wprintf . (Ein wC lc , lC , wc oder wC ist gleichbedeutend mit C in printf Funktionen und mit c in wprintf Funktionen.)
l oder w s, S oder Z wprintf Funktionen printf und wprintf . (Ein ls , lS , ws oder wS Typbezeichner ist gleichbedeutend mit S in printf Funktionen und mit s in wprintf Funktionen.)

Beachten Sie, dass die C , S und Z Konvertierungsspezifizierer und die I32 I , I32 , I64 und w Microsoft-Erweiterungen sind. Die Behandlung von l als Modifikator für long double anstelle von double unterscheidet sich vom Standard, obwohl Sie den Unterschied kaum erkennen können, es sei denn, long double hat eine andere Darstellung als double .

Formatflags drucken

Der C-Standard (auch C11 und C99) definiert die folgenden Flags für printf() :

Flagge Konvertierungen Bedeutung
- alles Das Ergebnis der Konvertierung ist innerhalb des Feldes linksbündig. Die Konvertierung ist rechtsbündig, wenn dieses Flag nicht angegeben ist.
+ signiert numerisch Das Ergebnis einer signierten Konvertierung beginnt immer mit einem Zeichen ('+' oder '-'). Die Konvertierung darf nur dann mit einem Vorzeichen beginnen, wenn ein negativer Wert konvertiert wird, wenn dieses Flag nicht angegeben ist.
<space> signiert numerisch Ist das erste Zeichen einer signierten Konvertierung kein Vorzeichen oder führt eine signierte Konvertierung zu keinen Zeichen, wird dem Ergebnis ein <space> vorangestellt. Das bedeutet, wenn das <space> und das ' + ' Flag beide erscheinen, wird das <space> Flag ignoriert.
# alles Gibt an, dass der Wert in ein alternatives Formular konvertiert werden soll. Für o Umwandlung, so hat er die Genauigkeit zu erhöhen, wenn und nur wenn notwendig, um die erste Ziffer des Ergebnisses zu zwingen , eine Null zu sein (wenn der Wert und Präzision beide 0 ist, wird eine einzelne 0 gedruckt). Für x oder X Konvertierungsbezeichner wird einem Ergebnis ungleich Null ein 0x (oder 0X ) vorangestellt. Für a , A , e , E , f , F , g , und G Konvertierungsspezifizierer, wird das Ergebnis immer ein Radix - Zeichen enthalten, auch wenn keine Ziffern stellen den radix Zeichen folgen. Ohne dieses Flag erscheint im Ergebnis dieser Konvertierungen nur ein Radix-Zeichen, wenn eine Ziffer darauf folgt. Bei g und G Konvertierungsspezifizierern werden nachfolgende Nullen nicht wie üblich aus dem Ergebnis entfernt. Bei anderen Konvertierungsspezifizierern ist das Verhalten undefiniert.
0 numerisch Für d, i, o, u, x, a, a, e, f, g, g und G-Konvertierungsspezifizierer werden führende Nullen (nach beliebigen Zeichen- oder Basisangaben) zum Auffüllen auf das Feld verwendet Breite anstelle von Leerzeichen, außer bei der Konvertierung einer Unendlichkeit oder eines NaN. Wenn die Flag '0' und '-' beide erscheinen, wird das Flag '0' ignoriert. Wenn für die Konvertierungskennungen d, i, o, u, x und X eine Genauigkeit angegeben wird, wird das Flag '0' ignoriert. ⌦ Wenn die Flags '0' und <apostrophe> angezeigt werden, werden die Gruppierungszeichen vor dem Auffüllen mit Nullen eingefügt. Bei anderen Konvertierungen ist das Verhalten undefiniert. ⌫

Diese Flags werden auch von Microsoft mit den gleichen Bedeutungen unterstützt.

Die POSIX-Spezifikation für printf() fügt hinzu:

Flagge Konvertierungen Bedeutung
' i, d, u, f, F, g, G Der ganzzahlige Teil des Ergebnisses einer Dezimalkonvertierung wird mit Gruppierungszeichen von Tausenden formatiert. Bei anderen Konvertierungen ist das Verhalten undefiniert. Das nicht monetäre Gruppierungszeichen wird verwendet.


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow