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

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.

K&R C89

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 .

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

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 lub e (lub w stylu F lub E w przypadku specyfikatora konwersji G ), w zależności od przeliczonej wartości i precyzji. Niech P 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 stylu E miałaby wykładnik X :

  • Jeżeli P> X> = -4, konwersja musi odbywać się stylem f (lub F ) i dokładnością P - (X+1) .
  • W przeciwnym razie konwersja będzie przeprowadzana według stylu e (lub E ) i dokładności P - 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.


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow