Cosa può succedere se si chiama printf con una stringa di formato errata?

O in altre parole: una stringa di formato errato printf / fprintf intero ( %d , %u , %ld , %lld ) può causare un arresto anomalo del programma o un comportamento indefinito?

Cosinder seguendo le righe di codice:

 #include  #include  int main() { std::cout << sizeof(int) << std::endl << sizeof(long) << std::endl; long a = 10; long b = 20; std::printf("%d, %d\n", a, b); return 0; } 

Risultato su architettura a 32 bit:

 4 4 10, 20 

Risultato su architettura a 64 bit:

 4 8 10, 20 

In ogni caso il programma stampa il risultato atteso. Lo so, se il valore long supera l’intervallo int , il programma stampa numeri errati – che è brutto, ma non influisce sullo scopo principale del programma -, ma oltre a questo, potrebbe accadere qualcosa di inaspettato?

Cosa può succedere se si chiama printf con una stringa di formato errata?

Tutto può succedere. È un comportamento indefinito!
Comportamento indefinito significa che tutto può succedere. Potrebbe mostrarti risultati che ti aspetti o potrebbero non andare in crash. Tutto può succedere e non puoi biasimare nessuno se non te stesso.

Riferimento:

c99 Standard: 7.19.6.1:
paragrafo 9:

Se una specifica di conversione non è valida, il comportamento non è definito. 225) Se un argomento non è il tipo corretto per la specifica della coverion corrispondente, il comportamento non è definito.

Oh sì – printf dipende dalla stringa di formato per determinare la dimensione e il tipo della variabile da recuperare successivamente. Quando la stringa di formato è sbagliata, può provare a recuperare una variabile che non è nemmeno lì, con tutte le conseguenze che possono avere.

È un comportamento indefinito – non c’è nulla nelle specifiche che dice al progettista di compilatori (o al progettista di librerie C) come dovrebbe essere gestito, e quindi è permesso loro di fare qualsiasi cosa.

In pratica, è uno di quelli in cui dipende interamente dall’interpretazione dei numeri e, molto probabilmente, non otterrete mai nulla di buono da questo. Le cose veramente brutte sono quando si mischia la stringa con la formattazione dei numeri interi – le stringhe si stampano bene come (strani, forse) numeri, ma i numeri difficilmente “funzionano” quando vengono passati come stringhe – perché una stringa è un puntatore all’indirizzo del primo carattere – e la maggior parte dei numeri non è un puntatore valido in un sistema tipico, quindi si bloccherà.

Ma non c’è alcuna garanzia di nulla. Nel tuo esempio a 64 bit, è chiaro che il numero è “little endian”. Prova la stessa cosa con 0x100000000, e stamperà 0 – perché il resto del numero è perso.

Tutto può succedere se printf viene chiamato con una stringa di formato errata. Il suo comportamento indefinito e uno non dovrebbe mai fare affidamento su un comportamento indefinito.

Non usare printf

printf è una reliquia dei giorni C, e non è più necessario … Utilizzare invece i manipolatori std::cout e I / O.