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
flube(lub w styluFlubEw przypadku specyfikatora konwersjiG), w zależności od przeliczonej wartości i precyzji. NiechPró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 styluEmiał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. |