Il problema con C variadics è che sono veramente avvitati in seguito, non proprio disegnato nella lingua. Il problema principale è che i parametri variadici sono anonimi, non hanno maniglie, non identificatori. Ciò porta alle macro VA ingombranti per generare riferimenti a parametri senza nomi. Ciò porta anche alla necessità di dire a quelle macro dove inizia l'elenco variadic e che tipo di parametri dovrebbero essere.
Tutte queste informazioni dovrebbero essere codificate in una sintassi corretta nella lingua stessa.
Ad esempio, si potrebbe estendere sintassi C esistente con parametri formali dopo l'ellissi, in questo modo
void foo (... int counter, float arglist);
Per convenzione, il primo parametro potrebbe essere per il numero di argomenti e la seconda per la lista degli argomenti. All'interno del corpo della funzione, l'elenco potrebbe essere trattato sintatticamente come una matrice.
Con tale convenzione, i parametri variadici non sarebbero più anonimi. All'interno del corpo della funzione, il contatore può essere indicato come qualsiasi altro parametro e gli elementi dell'elenco può fare riferimento come se fossero elementi array di un parametro di matrice, in questo modo
void foo (... int counter, float arglist) {
unsigned i;
for (i=0; i<counter; i++) {
printf("list[%i] = %f\n", i, arglist[i]);
}
}
Con una tale caratteristica integrata nel linguaggio stesso ogni riferimento a arglist[i]
verrebbe quindi tradotto nei rispettivi indirizzi sullo stack frame. Non ci sarebbe bisogno di farlo via macro.
Inoltre, il conteggio degli argomenti verrà automaticamente inserito dal compilatore, riducendo ulteriormente le possibilità di errore.
Una chiamata
foo(1.23, 4.56, 7.89);
sarà compilato come se fosse stata scritta
foo(3, 1.23, 4.56, 7.89);
All'interno del corpo della funzione, qualsiasi accesso ad un elemento oltre il numero effettivo di argomenti effettivamente passati potrebbe essere controllati in fase di esecuzione e causano un errore in fase di compilazione, migliorando così notevolmente la sicurezza.
Ultimo ma non meno importante, tutti i parametri variadici sono digitati e possono essere controllati in fase di compilazione, proprio come i parametri non-variabili sono controllati.
In alcuni casi d'uso sarebbe auspicabile avere tipi alternativi, ad esempio quando si scrive una funzione per memorizzare chiavi e valori in una raccolta. Questo potrebbe anche essere ospitati semplicemente consentendo parametri più formali dopo i puntini di sospensione, in questo modo
void store (collection dict, ... int counter, key_t key, val_t value);
Questa funzione potrebbe quindi essere chiamato come
store(dict, key1, val1, key2, val2, key3, val3);
ma sarebbe stato compilato come se fosse stata scritta
store(dict, 3, key1, val1, key2, val2, key3, val3);
I tipi di parametri effettivi verrebbero confrontati con il tempo di compilazione rispetto ai corrispondenti parametri variadici formali.
All'interno del corpo della funzione contatore sarebbe nuovamente riferimento dal relativo identificatore, chiavi e valori dovrebbe essere indicata come se fossero array,
key[i]
riferisce alla chiave della chiave/coppia valore i-esimo value[i]
riferisce al valore della coppia valore i-esimo
e questi riferimenti sarebbero compilati ai rispettivi indirizzi sul telaio dello stack.
Niente di tutto questo è veramente difficile da fare, né è mai stato. Tuttavia, la filosofia di progettazione di C semplicemente non è favorevole a tali caratteristiche.
Senza un programmatore di avventurarsi compilatore C (o C preprocessore implementor) prendendo il comando per implementare questo o uno schema simile è improbabile che ci sarà mai visto nulla del genere in C.
Il problema è che la gente che sono interessati alla sicurezza del tipo e disposti a mettere il lavoro per costruire i propri compilatori di solito giungono alla conclusione che il linguaggio C è al di là del salvataggio e si può anche ricominciare con un linguaggio meglio progettato per cominciare.
Sono stato lì da solo, alla fine ho deciso di abbandonare il tentativo, quindi di implementare una delle lingue di Wirth e aggiunto tipi di variadics sicuri invece. Da allora mi imbatto in altre persone che mi hanno raccontato dei loro tentativi abortiti. Il tipo corretto di variadici sicure in C sembra pronto a rimanere elusivo.
Se tutti i tipi devono essere dello stesso tipo, hai preso in considerazione solo il passaggio di un array di essi? –
Nessun array nativo in C89. Non puoi passare ad esempio, 'f ({1,2,3,0}}' con il compilatore MS C. – mikebloch
vuoi qualcosa che funzioni con gcc o MS C? Si prega di taggare in modo appropriato. Con C99 ci sono soluzioni che sono typesafe. –