C Language
Input / Output formattato
Ricerca…
Stampa del valore di un puntatore su un oggetto
Per stampare il valore di un puntatore su un oggetto (al contrario di un puntatore di funzione), utilizzare lo specificatore di conversione p
. È stato definito per stampare solo i segnapunti void
, quindi per stampare il valore di un punto non void
deve essere convertito in modo esplicito ("castato *") per 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;
}
Usando <inttypes.h>
e uintptr_t
Un altro modo per stampare i puntatori in C99 o uintptr_t
successive utilizza il tipo uintptr_t
e le macro da <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;
}
In teoria, potrebbe non esserci un tipo intero che può contenere qualsiasi puntatore convertito in un numero intero (quindi il tipo uintptr_t
potrebbe non esistere). In pratica, esiste. I puntatori alle funzioni non devono essere convertibili nel tipo uintptr_t
, anche se spesso sono più convertibili.
Se il tipo uintptr_t
esiste, lo stesso intptr_t
tipo intptr_t
. Non è chiaro il motivo per cui si vorrebbe mai trattare gli indirizzi come interi con segno, però.
Storia pre-standard:
Prima di C89 durante i tempi di K & R-C non c'era nessun tipo void*
(né header <stdlib.h>
, né prototipi, e quindi nessuna notazione int main(void)
), quindi il puntatore è stato castato su long unsigned int
e stampato usando il modificatore di lunghezza / identificatore di conversione lx
.
L'esempio sotto è solo a scopo informativo. Oggigiorno questo è un codice non valido, che molto bene potrebbe provocare il famigerato comportamento indefinito .
#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;
}
Stampa della differenza dei valori di due puntatori su un oggetto
Sottraendo i valori di due puntatori a un oggetto si ottiene un numero intero con segno * 1 . Quindi verrebbe stampato utilizzando almeno lo specifier di conversione d
.
Per assicurarsi che ci sia un tipo abbastanza largo da contenere una "differenza puntatore", dato che C99 <stddef.h>
definisce il tipo ptrdiff_t
. Per stampare un ptrdiff_t
usa il modificatore di lunghezza 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;
}
Il risultato potrebbe essere simile a questo:
p1 = 0x7fff6679f430
p2 = 0x7fff6679f434
p2 - p1 = 1
Si noti che il valore risultante della differenza viene ridimensionato in base alla dimensione del puntatore sottratto dal puntatore, un int
qui. La dimensione di un int
per questo esempio è 4.
* 1 Se i due puntatori da sottrarre non puntano allo stesso oggetto, il comportamento non è definito.
Specifiers di conversione per la stampa
Identificatore di conversione | Tipo di argomento | Descrizione |
---|---|---|
i , d | int | stampa decimale |
u | int non firmato | stampa decimale |
o | int non firmato | stampa ottale |
x | int non firmato | stampa esadecimale, minuscolo |
X | int non firmato | stampa esadecimale, maiuscolo |
f | Doppio | stampa fluttuante con una precisione predefinita di 6, se non viene fornita alcuna precisione (minuscole utilizzate per numeri speciali nan e inf o infinity ) |
F | Doppio | stampa fluttuante con una precisione predefinita di 6, se non viene fornita alcuna precisione (maiuscole utilizzate per numeri speciali NAN e INF o INFINITY ) |
e | Doppio | le stampe fluttuano con una precisione predefinita di 6, se non viene data alcuna precisione, usando la notazione scientifica usando mantissa / esponente; esponente minuscolo e numeri speciali |
E | Doppio | le stampe fluttuano con una precisione predefinita di 6, se non viene data alcuna precisione, usando la notazione scientifica usando mantissa / esponente; esponente maiuscolo e numeri speciali |
g | Doppio | utilizza o f o e [vedi sotto] |
G | Doppio | usa F o E [vedi sotto] |
a | Doppio | stampa esadecimale, minuscolo |
A | Doppio | stampa esadecimale, maiuscolo |
c | carbonizzare | stampa carattere singolo |
s | char * | stampa una stringa di caratteri fino a un terminatore NUL o troncato a lunghezza data dalla precisione, se specificato |
p | void * | stampa void -pointer value; un void non void dovrebbe essere convertito esplicitamente ("cast") a void* ; puntatore all'oggetto solo, non a un puntatore di funzione |
% | n / A | stampa il carattere % |
n | int * | scrivere il numero di byte stampati finora nel int indicò. |
Si noti che i modificatori di lunghezza possono essere applicati a %n
(ad esempio %hhn
indica che un %hhn
conversione n
successivo si applica a un puntatore a un argomento signed char
, in base alla ISO / IEC 9899: 2011 §7.21.6.1 ¶7).
Si noti che le conversioni in virgola mobile si applicano ai tipi float
e double
causa delle regole di promozione predefinite - §6.5.2.2 Chiamate di funzione, ¶ 7 La notazione dei puntini di sospensione in un dichiaratore di prototipo di funzione causa l'interruzione della conversione del tipo di argomento dopo l'ultimo parametro dichiarato. Le promozioni degli argomenti predefiniti vengono eseguite sugli argomenti finali. Quindi, funzioni come printf()
sono sempre passate solo double
valori, anche se la variabile di riferimento è di tipo float
.
Con i formati g
e G
, la scelta tra la notazione e
ed f
(o E
e F
) è documentata nello standard C e nelle specifiche POSIX per printf()
:
Il doppio argomento che rappresenta un numero in virgola mobile deve essere convertito nello stile
f
oe
(o nello stileF
oE
nel caso di unG
conversioneG
), a seconda del valore convertito e della precisione. SiaP
la precisione se non zero, 6 se la precisione è omessa, o 1 se la precisione è zero. Quindi, se una conversione con lo stileE
avrebbe un esponente diX
:
- Se P> X> = -4, la conversione deve essere con lo stile
f
(oF
) e con precisioneP - (X+1)
.- Altrimenti, la conversione deve essere con stile
e
(oE
) e precisioneP - 1
.
Infine, a meno che non sia usato il contrassegno "#", tutti gli zeri finali devono essere rimossi dalla parte frazionaria del risultato e il carattere del punto decimale deve essere rimosso se non è rimasta alcuna parte frazionaria.
La funzione printf ()
Acceduto tramite l'inclusione di <stdio.h>
, la funzione printf()
è lo strumento principale utilizzato per stampare il testo sulla console in C.
printf("Hello world!");
// Hello world!
Gli array di caratteri normali e non formattati possono essere stampati da soli posizionandoli direttamente tra le parentesi.
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
In alternativa, è possibile stampare numeri interi, numeri in virgola mobile, caratteri e altro utilizzando il carattere di escape %
, seguito da un carattere o sequenza di caratteri che denotano il formato, noto come specificatore di formato .
Tutti gli argomenti aggiuntivi alla funzione printf()
sono separati da virgole e questi argomenti dovrebbero essere nello stesso ordine degli specificatori di formato. Argomenti aggiuntivi vengono ignorati, mentre gli argomenti digitati in modo errato o la mancanza di argomenti causano errori o comportamenti non definiti. Ogni argomento può essere un valore letterale o una variabile.
Al termine dell'esecuzione, il numero di caratteri stampati viene restituito con tipo int
. In caso contrario, un errore restituisce un valore negativo.
Modificatori di lunghezza
Gli standard C99 e C11 specificano i seguenti modificatori di lunghezza per printf()
; i loro significati sono:
Modificatore | Modifica | Si applica a |
---|---|---|
hh | d, i, o, u, x o X | char , char signed char o unsigned char |
h | d, i, o, u, x o X | short int o unsigned short int |
l | d, i, o, u, x o X | long int o unsigned long int |
l | a, A, e, E, f, F, g o G | double (per compatibilità con scanf() ; indefinito in C90) |
ll | d, i, o, u, x o X | long long int o unsigned long long int |
j | d, i, o, u, x o X | intmax_t o uintmax_t |
z | d, i, o, u, x o X | size_t o il tipo firmato corrispondente ( ssize_t in POSIX) |
t | d, i, o, u, x o X | ptrdiff_t o il corrispondente numero intero senza segno |
L | a, A, e, E, f, F, g o G | long double |
Se un modificatore di lunghezza viene visualizzato con un identificatore di conversione diverso da quello specificato sopra, il comportamento non è definito.
Microsoft specifica alcuni modificatori di lunghezza diversi e in modo esplicito non supporta hh
, j
, z
o t
.
Modificatore | Modifica | Si applica a |
---|---|---|
I32 | d, i, o, x o X | __int32 |
I32 | o, u, x o X | unsigned __int32 |
I64 | d, i, o, x o X | __int64 |
I64 | o, u, x o X | unsigned __int64 |
io | d, i, o, x o X | ptrdiff_t (cioè __int32 su __int32 a 32 bit, __int64 su piattaforme a 64 bit) |
io | o, u, x o X | size_t (ovvero, unsigned __int32 su unsigned __int32 a 32 bit, unsigned __int64 su piattaforme a 64 bit) |
io L | a, A, e, E, f, g o G | long double (In Visual C ++, anche se long double è un tipo distinto, ha la stessa rappresentazione interna del double ). |
io w | c o C | Ampio personaggio con funzioni printf e wprintf . (Un wC tipo lc , lC , wc o wC è sinonimo di C nelle funzioni printf e con c nelle funzioni wprintf .) |
io w | s, S o Z | Stringa di caratteri wprintf funzioni printf e wprintf . (Un wS tipo ls , lS , ws o wS è sinonimo di S nelle funzioni printf e con s nelle funzioni wprintf .) |
Notare che gli Z
conversione C
, S
e Z
ei modificatori di lunghezza I
, I32
, I64
e w
sono estensioni Microsoft. Trattare l
come modificatore per il long double
anziché il double
è diverso dallo standard, anche se sarà difficile individuare la differenza a meno che il long double
non abbia una rappresentazione diversa dal double
.
Flag di formato di stampa
Lo standard C (C11 e C99) definisce i seguenti flag per printf()
:
Bandiera | conversioni | Senso |
---|---|---|
- | tutti | Il risultato della conversione deve essere giustificato a sinistra all'interno del campo. La conversione è giustificata a destra se questo flag non è specificato. |
+ | numerico firmato | Il risultato di una conversione firmata inizia sempre con un segno ('+' o '-' '). La conversione inizia con un segno solo quando un valore negativo viene convertito se questo flag non è specificato. |
<space> | numerico firmato | Se il primo carattere di una conversione firmata non è un segno o se una conversione firmata non produce alcun carattere, uno <space> deve essere preceduto dal risultato. Ciò significa che se appaiono entrambi i flag <space> e " + ", il flag <space> deve essere ignorato. |
# | tutti | Specifica che il valore deve essere convertito in un modulo alternativo. Per o conversione, essa aumenta la precisione, se e solo se necessario, di forzare la prima cifra del risultato da uno zero (se il valore e la precisione sono entrambi 0, un singolo 0 è stampato). Per gli specificatori di conversione x o X , un risultato diverso da zero deve avere 0x (o 0X ) come prefisso. Per gli specificatori di conversione a , A , e , E , f , F , g e G , il risultato deve sempre contenere un carattere di radice, anche se nessuna cifra segue il carattere di radice. Senza questo flag, un carattere di radice appare nel risultato di queste conversioni solo se una cifra lo segue. Per gli specificatori di conversione g e G , gli zeri finali non devono essere rimossi dal risultato come normalmente. Per altri specificatori di conversione, il comportamento non è definito. |
0 | numerico | Per gli identificatori di conversione d, i, o, u, x, X, a, A, e, E, f, G e G, gli zeri iniziali (a seguito di qualsiasi indicazione di segno o base) vengono utilizzati per eseguire il rilievo sul campo larghezza invece di eseguire il riempimento dello spazio, tranne quando si converte un infinito o NaN. Se appaiono entrambi i flag "0" e "-", il flag "0" viene ignorato. Per gli identificatori di conversione d, i, o, u, xe X, se viene specificata una precisione, il flag '0' deve essere ignorato. ⌦ Se appaiono entrambi i flag "0" e <apostrophe> , i caratteri di raggruppamento vengono inseriti prima dello zero padding. Per le altre conversioni, il comportamento non è definito. ⌫ |
Questi flag sono supportati anche da Microsoft con lo stesso significato.
La specifica POSIX per printf()
aggiunge:
Bandiera | conversioni | Senso |
---|---|---|
' | i, d, u, f, F, g, G | La parte intera del risultato di una conversione decimale deve essere formattata con migliaia di caratteri di raggruppamento. Per altre conversioni il comportamento non è definito. Viene utilizzato il carattere di raggruppamento non monetario. |