2009-03-31 4 views
5

Stavo solo guardando la pagina man di printf e mi è venuto in mente qualcosa. Mi chiedevo se ci fossero "avvocati linguistici" qui che potrebbero rispondere ad una domanda relativamente semplice :-P.domanda sugli identificatori di formato printf incompatibili

Così il modificatore 't' è definito come

Una successiva conversione intero corrisponde ad un argomento ptrdiff_t.

Allora, qual è supposta che accada se si combina questo con una conversione intero senza segno? Chiaramente o, u, x e X sono tutti intesi per essere interpretati come valori senza segno, mentre d e i sono firmati.

Allo stesso modo, esistono versioni firmate/non firmate per tutti i modificatori (int/unsigned int, size_t/ssize_t ecc. Eccetto ptrdiff_t.

In pratica, non succede nulla di male poiché le versioni non firmate di tipi occupano la stessa quantità di spazio delle versioni firmate. Quindi il diritto dei byte viene estratto dallo stack.

Quindi niente "cattivo" accade, infatti, nelle stampe il valore atteso per tutte le cose testate ad eccezione del "INT_MIN" (assumendo che sizeof(int) == sizeof(ptrdiff_t).

printf("%tu %td\n", INT_MIN, INT_MIN); 

stampe

2147483648 -2147483648 

su un Sistema a 32 bit

Lo standard ha qualche opinione in proposito? Penso che la risposta sarà "comportamento indefinito". Ma ho pensato che avrei chiesto;).

+0

Questo ha niente a che fare con C++ (almeno prima di C++ 0x)? Printf() ecc sta per essere modificato in C++ 0x per conformarsi a C99? Penso che dovresti rimuovere il tag C++. –

+0

ptrdiff_t è definito in cstddef in C++. printf ovviamente esiste anche in C++. Non sono a conoscenza di C++ 0x cambiando affatto printf. –

+0

hrmm, sembra che C++ non abbia il modificatore c99 't'. Giusto. –

risposta

3

Niente da vedere qui. Il codice che hai scritto è legale.

Solo alcuni fatti per spiegare perché:

  • tutti i tipi interi firmati hanno controparti senza segno, con gli stessi requisiti di formato/allineamento
  • ptrdiff_t è stato prescritto per essere un tipo intero con segno dallo standard. Pertanto, ha un gemello non firmato. (In realtà, la logica simile vale per size_t così - ssize_t non è C, ma POSIX)
  • il t lunghezza specificatore deve lavorare con d, i, o, u, x, X tipi
+0

qual è l'equivalente unsigned valido per ptrdiff_t? – user83255

+0

Non ha un nome speciale - puoi solo dire che se ptrdiff_t è "long long" allora la sua controparte non firmata è "unsigned long long" ecc. – jpalecek

+0

Il fatto importante che è stato omesso è che, nei casi in cui il valore si adatta alle varianti firmate e non firmate di un tipo intero, ha la stessa rappresentazione e lo standard consente esplicitamente di passare il tipo di argomento "errato" in questo caso (che è possibile solo per funzioni senza prototipi e funzioni variadiche, comunque). Per quanto posso dire, sarebbe UB a passare un valore negativo 'ptrdiff_t' quando lo specificatore di formato si aspetta un tipo senza segno. –