Ecco lo C99 standard; I tipi "auto-promuoventi" sono quelli che si promuovono quando vengono applicate le promozioni di argomento predefinito (paragrafo 6.5.2.2, paragrafo 6, che fa riferimento alle promozioni intere descritte in §6.3.1.1).
La mia lettura della definizione va_arg
(§7.15.1.1) è che questa limitazione è implicita dallo standard. La parte rilevante è nel paragrafo 2:
[...] o se tipo non è compatibile con il tipo di argomento attuale successiva (come promosso secondo le promozioni di argomento di default) [... ]
che è abbastanza chiara sul tipo di argomento attuale successiva di essere promosso, ma ho letto da non dire nulla su tipo promosso. (Penso che la clausola "(come promosso ...)" sia solo un promemoria che le promozioni degli argomenti predefiniti vengono eseguite sugli argomenti finali quando viene chiamata una funzione varargs.)
Questo elemento nell'elenco di comportamento non definito in § J.2 supporta questa lettura:
- la va_arg
macro viene invocato quando non v'è alcun argomento reale prossimo, o con un tipo specificato che non è compatibile con il tipo promosso del reale argomento successivo, con una certa eccezioni (7.15.1.1).
(anche se sì, lo so, l'allegato J è "informativo" piuttosto che "normativo" ...).
In questo caso: va_arg(ap, float)
(per esempio) non può essere valido - tipo in questo caso è float
, ma il tipo promosso dell'argomento effettiva successivo potrà eventualmente essere float
(un argomento float
sarebbe promosso double
).
fonte
2011-01-13 00:33:52
C'è qualche motivo particolare per questa restrizione? Forse qualcosa a che fare con l'implementazione? Va_arg'? –
@crypto: Sospetto che Zack abbia ragione (vedere la sua risposta a Jens); non c'è un modo ovvio per trovare la promozione di argomento predefinita di un dato tipo senza l'aiuto speciale del compilatore, quindi questo consente un'implementazione di va_arg (ap, type) 'che funziona senza tale aiuto. (ad esempio, mantieni un puntatore di byte all'argomento corrente sullo stack in "ap", quindi "va_arg" potrebbe essere una qualche orribile macro che passa all'argomento successivo eseguendo il cast di "type *", incrementando il puntatore "type *", e ritorno a un puntatore di byte.) –