C Language
Sformatowane wejście / wyjście
Szukaj…
Drukowanie wartości wskaźnika na obiekcie
Aby wydrukować wartość wskaźnika na obiekcie (w przeciwieństwie do wskaźnika funkcji), użyj specyfikatora konwersji p
. Jest zdefiniowany, aby drukować tylko void
punkty, więc aby wydrukować wartość nie- void
wskaźnika, należy go jawnie przekonwertować („rzutować *”) na 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;
}
Używanie <inttypes.h>
i uintptr_t
Inny sposób drukowania wskaźników w C99 lub nowszym wykorzystuje typ uintptr_t
i makra z <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;
}
Teoretycznie może nie istnieć typ liczby całkowitej, który może przechowywać dowolny wskaźnik przekonwertowany na liczbę całkowitą (więc typ uintptr_t
może nie istnieć). W praktyce istnieje. Wskaźniki do funkcji nie muszą być konwertowane na typ uintptr_t
- choć znowu najczęściej są one konwertowalne.
Jeśli istnieje typ uintptr_t
, to również typ intptr_t
. Nie jest jednak jasne, dlaczego miałbyś kiedykolwiek traktować adresy jako liczby całkowite ze znakiem.
Historia przedstandardowa:
Przed C89 w czasach K&R-C nie było typu void*
(ani nagłówka <stdlib.h>
, ani prototypów, a zatem nie ma notacji int main(void)
), więc wskaźnik był rzutowany na long unsigned int
i drukowany za pomocą lx
długość / modyfikator specyfikator konwersji.
Poniższy przykład służy wyłącznie celom informacyjnym. W dzisiejszych czasach jest to nieprawidłowy kod, który bardzo dobrze może sprowokować niesławne Niezdefiniowane Zachowanie .
#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;
}
Drukowanie różnicy wartości dwóch wskaźników do obiektu
Po odjęciu wartości dwóch wskaźników do obiektu powstaje liczba całkowita ze znakiem * 1 . Zostałby więc wydrukowany przy użyciu co najmniej specyfikatora konwersji d
.
Aby upewnić się, że typ jest wystarczająco szeroki, aby pomieścić taką „różnicę wskaźnika”, ponieważ C99 <stddef.h>
definiuje typ ptrdiff_t
. Aby wydrukować ptrdiff_t
użyj modyfikatora długości t
.
#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;
}
Wynik może wyglądać następująco:
p1 = 0x7fff6679f430
p2 = 0x7fff6679f434
p2 - p1 = 1
Należy pamiętać, że wynikowa wartość różnicy jest skalowana przez rozmiar typu, do którego odejmowane są wskaźniki, int
tutaj. Rozmiar int
dla tego przykładu wynosi 4.
* 1 Jeśli dwa wskaźniki, które mają zostać odjęte, nie wskazują tego samego obiektu, zachowanie jest niezdefiniowane.
Specyfikatory konwersji do drukowania
Specyfikator konwersji | Rodzaj argumentu | Opis |
---|---|---|
i , d | int | drukuje dziesiętnie |
u | unsigned int | drukuje dziesiętnie |
o | unsigned int | drukuje ósemkowo |
x | unsigned int | drukuje szesnastkowo, małe litery |
X | unsigned int | drukuje szesnastkowo, wielkie litery |
f | podwójnie | drukuje zmiennoprzecinkową z domyślną precyzją 6, jeśli nie podano dokładności (małe litery używane dla liczb specjalnych nan i inf lub infinity ) |
F | podwójnie | drukuje liczbę zmiennoprzecinkową z domyślną precyzją 6, jeśli nie podano dokładności (wielkie litery używane w przypadku numerów specjalnych NAN i INF lub INFINITY ) |
e | podwójnie | drukuje zmiennoprzecinkową z domyślną precyzją 6, jeśli nie podano precyzji, z wykorzystaniem notacji naukowej z wykorzystaniem mantysy / wykładnika; wykładnik małych liter i liczby specjalne |
E | podwójnie | drukuje zmiennoprzecinkową z domyślną precyzją 6, jeśli nie podano precyzji, z wykorzystaniem notacji naukowej z wykorzystaniem mantysy / wykładnika; wykładnik wielkich liter i liczby specjalne |
g | podwójnie | używa f lub e [patrz poniżej] |
G | podwójnie | używa F lub E [patrz poniżej] |
a | podwójnie | drukuje szesnastkowo, małe litery |
A | podwójnie | drukuje szesnastkowo, wielkie litery |
c | zwęglać | drukuje pojedynczy znak |
s | zwęglać* | wypisuje ciąg znaków do terminatora NUL lub obcięty do długości podanej przez precyzję, jeśli jest określona |
p | unieważnić* | wypisuje void -pointer wartość; wskaźnik non void powinien zostać jawnie przekonwertowany („obsada”) na void* ; wskaźnik tylko do obiektu, a nie wskaźnik funkcji |
% | nie dotyczy | wypisuje znak % |
n | int * | napisz liczbę bajtów wydrukowanych do tej pory w wskazanej int . |
Zauważ, że modyfikatory długości mogą być zastosowane do %n
(np. %hhn
wskazuje, że następny n
specyfikator konwersji ma zastosowanie do wskaźnika do argumentu signed char
, zgodnie z ISO / IEC 9899: 2011, § 7.21.6.1 ¶7).
Zauważ, że konwersje zmiennoprzecinkowe mają zastosowanie do typów float
i double
powodu domyślnych reguł promocji - §6.5.2.2 Wywołania funkcji, ¶7 Notacja elipsy w deklaratorze prototypu funkcji powoduje zatrzymanie konwersji typu argumentu po ostatnim zadeklarowanym parametrze. Domyślne promocje argumentów są wykonywane na końcowych argumentach. ) Zatem funkcje takie jak printf()
otrzymują double
wartości, nawet jeśli zmienna, do której się odwołuje, jest typu float
.
W przypadku formatów g
G
wybór między oznaczeniami e
i f
(lub E
i F
) jest udokumentowany w standardzie C oraz w specyfikacji POSIX dla printf()
:
Podwójny argument reprezentujący liczbę zmiennoprzecinkową przekształca się w stylu
f
lube
(lub w styluF
lubE
w przypadku specyfikatora konwersjiG
), w zależności od przeliczonej wartości i precyzji. NiechP
równa się precyzji, jeśli niezerowa, 6, jeśli precyzja jest pominięta, lub 1, jeśli precyzja wynosi zero. Następnie, jeśli konwersja w styluE
miałaby wykładnikX
:
- Jeżeli P> X> = -4, konwersja musi odbywać się stylem
f
(lubF
) i dokładnościąP - (X+1)
.- W przeciwnym razie konwersja będzie przeprowadzana według stylu
e
(lubE
) i dokładnościP - 1
.
Wreszcie, chyba że użyto flagi „#”, wszelkie zera końcowe należy usunąć z części ułamkowej wyniku, a znak kropki dziesiętnej należy usunąć, jeśli nie pozostała część ułamkowa.
Funkcja printf ()
Dostępna poprzez <stdio.h>
, funkcja printf()
jest podstawowym narzędziem używanym do drukowania tekstu na konsoli w C.
printf("Hello world!");
// Hello world!
Normalne, niesformatowane tablice znaków można wydrukować same, umieszczając je bezpośrednio między nawiasami.
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
Alternatywnie liczby całkowite, liczby zmiennoprzecinkowe, znaki i więcej można wydrukować przy użyciu znaku zmiany znaczenia %
, po którym następuje znak lub sekwencja znaków oznaczających format, znany jako specyfikator formatu .
Wszystkie dodatkowe argumenty funkcji printf()
są oddzielone przecinkami, a argumenty te powinny być w tej samej kolejności co specyfikatory formatu. Dodatkowe argumenty są ignorowane, a niepoprawnie wpisane lub brak argumentów spowoduje błędy lub niezdefiniowane zachowanie. Każdy argument może być wartością dosłowną lub zmienną.
Po pomyślnym wykonaniu liczba drukowanych znaków jest zwracana za pomocą typu int
. W przeciwnym razie błąd zwraca wartość ujemną.
Modyfikatory długości
Standardy C99 i C11 określają następujące modyfikatory długości dla printf()
; ich znaczenia to:
Modyfikator | Modyfikuje | Dotyczy |
---|---|---|
hh | d, i, o, u, x lub X | char , signed char lub unsigned char |
h | d, i, o, u, x lub X | short int lub unsigned short int |
l | d, i, o, u, x lub X | long int lub unsigned long int |
l | a, A, e, E, f, F, g lub G | double (dla kompatybilności ze scanf() ; niezdefiniowany w C90) |
ll | d, i, o, u, x lub X | long long int lub unsigned long long int |
jot | d, i, o, u, x lub X | intmax_t lub uintmax_t |
z | d, i, o, u, x lub X | size_t lub odpowiedni podpisany typ ( ssize_t w POSIX) |
t | d, i, o, u, x lub X | ptrdiff_t lub odpowiadający mu typ całkowity bez znaku |
L. | a, A, e, E, f, F, g lub G | long double |
Jeśli z dowolnym specyfikatorem konwersji innym niż określony powyżej pojawia się modyfikator długości, zachowanie jest niezdefiniowane.
Microsoft określa różne modyfikatory długości i jawnie nie obsługuje hh
, j
, z
ani t
.
Modyfikator | Modyfikuje | Dotyczy |
---|---|---|
I32 | d, i, o, x lub X | __int32 |
I32 | o, u, x lub X | unsigned __int32 |
I64 | d, i, o, x lub X | __int64 |
I64 | o, u, x lub X | unsigned __int64 |
ja | d, i, o, x lub X | ptrdiff_t (to znaczy __int32 na platformach 32-bitowych, __int64 na platformach 64-bitowych) |
ja | o, u, x lub X | size_t (to znaczy unsigned __int32 na platformach 32-bitowych, unsigned __int64 na platformach 64-bitowych) |
l lub L | a, A, e, E, f, g lub G | long double (W Visual C ++, chociaż long double jest odrębnym typem, ma taką samą wewnętrzną reprezentację jak double ). |
l lub w | c lub C. | Szeroki znak z funkcjami printf i wprintf . ( wC typu lc , lC , wc lub wC jest synonimem C w funkcjach printf i c funkcjach wprintf .) |
l lub w | s, S lub Z | Ciąg znaków o szerokim znaku z funkcjami printf i wprintf . ( wS typu ls , lS , ws lub wS jest synonimem S w funkcjach printf i s funkcjach wprintf .) |
Uwaga: specyfikatory konwersji C
, S
i Z
oraz modyfikatory długości I
, I32
, I64
i w
są rozszerzeniami Microsoft. Traktowanie l
jako modyfikatora dla long double
zamiast double
różni się od standardu, chociaż będziesz ciężko zauważyć różnicę, chyba że long double
ma inną reprezentację niż double
.
Drukowanie flag formatu
Standard C (także C11 i C99) definiuje następujące flagi dla printf()
:
Flaga | Konwersje | Znaczenie |
---|---|---|
- | wszystko | Wynik konwersji należy uzasadnić w polu. Konwersja jest uzasadniona, jeśli ta flaga nie jest określona. |
+ | podpisany numerycznie | Wynik podpisanej konwersji zawsze zaczyna się znakiem („+” lub „-”). Konwersja rozpoczyna się znakiem tylko wtedy, gdy wartość ujemna jest konwertowana, jeżeli ta flaga nie jest określona. |
<space> | podpisany numerycznie | Jeśli pierwszy znak podpisanej konwersji nie jest znakiem lub jeśli podpisana konwersja nie powoduje żadnych znaków, do wyniku należy wstawić <space> . Oznacza to, że jeśli pojawią się zarówno flagi <space> i „ + ”, flaga <space> powinna zostać zignorowana. |
# | wszystko | Określa, że wartość ma zostać przekonwertowana na alternatywną formę. W przypadku konwersji o , zwiększa ona dokładność, jeśli i tylko w razie potrzeby, aby zmusić pierwszą cyfrę wyniku do zera (jeśli zarówno wartość, jak i precyzja są równe 0, drukowane jest pojedyncze 0). W przypadku specyfikatorów konwersji x lub X wynik niezerowy powinien mieć przedrostek 0x (lub 0X ). W przypadku specyfikatorów konwersji a , A , e , E , f , F , g i G wynik zawsze musi zawierać znak podstawnika, nawet jeśli żadna cyfra nie występuje po znaku podstawnika. Bez tej flagi znak podstawowy pojawia się w wyniku tych konwersji tylko wtedy, gdy następuje po nim cyfra. W przypadku specyfikatorów konwersji g G zera końcowe nie powinny być usuwane z wyniku, jak zwykle. W przypadku innych specyfikatorów konwersji zachowanie jest niezdefiniowane. |
0 | numeryczny | W przypadku specyfikatorów konwersji d, i, o, u, x, X, a, A, e, E, f, F, g i G zera wiodące (po dowolnym znaku znaku lub podstawie) są używane do wypełnienia pola szerokość zamiast wypełniania spacją, z wyjątkiem konwersji nieskończoności lub NaN. Jeśli pojawią się flagi „0” i „-”, flaga „0” jest ignorowana. W przypadku specyfikatorów konwersji d, i, o, u, x i X, jeśli określono precyzję, flaga „0” zostanie zignorowana. ⌦ Jeśli pojawią się flagi „0” i <apostrophe> , znaki grupujące są wstawiane przed dopełnianiem zera. W przypadku innych konwersji zachowanie jest niezdefiniowane. ⌫ |
Te flagi są również obsługiwane przez Microsoft w tych samych znaczeniach.
Specyfikacja POSIX dla printf()
dodaje:
Flaga | Konwersje | Znaczenie |
---|---|---|
' | i, d, u, f, F, g, G | Część całkowitą wyniku konwersji dziesiętnej należy sformatować przy użyciu tysięcy znaków grupujących. W przypadku innych konwersji zachowanie jest niezdefiniowane. Używany jest niepieniężny znak grupujący. |