El problema con C variadics es que realmente están atornillados después, no es realmente diseñado a la lengua. El principal problema es que los parámetros variados son anónimos, no tienen identificadores ni identificadores. Esto lleva a las macros VA inmanejables para generar referencias a parámetros sin nombres. También lleva a la necesidad de contar esas macros donde comienza la lista variadic y de qué tipo se espera que sean los parámetros.
Toda esta información realmente debería estar codificada con la sintaxis adecuada en el idioma en sí.
Por ejemplo, se podría extender la sintaxis de C existente con parámetros formales después de la elipsis, al igual que
void foo (... int counter, float arglist);
Por convención, el primer parámetro podría ser para el número del argumento y el segundo para la lista de argumentos. Dentro del cuerpo de la función, la lista podría tratarse sintácticamente como una matriz.
Con tal convención, los parámetros variadic ya no serían anónimos. Dentro del cuerpo de la función, el contador puede ser referenciado como cualquier otro parámetro y los elementos de la lista se puede hacer referencia como si fueran elementos de la matriz de un parámetro de matriz, al igual que
void foo (... int counter, float arglist) {
unsigned i;
for (i=0; i<counter; i++) {
printf("list[%i] = %f\n", i, arglist[i]);
}
}
Con esta característica integrada en la propia lengua , cada referencia a arglist[i]
se traduciría a las direcciones respectivas en el marco de la pila. No habría necesidad de hacer esto a través de macros.
Además, el recuento de argumentos sería insertado automáticamente por el compilador, reduciendo aún más la posibilidad de error.
Una llamada a
foo(1.23, 4.56, 7.89);
se compilará como si hubiera sido escrito
foo(3, 1.23, 4.56, 7.89);
Dentro del cuerpo de la función, cualquier acceso a un elemento más allá del número real de los argumentos que se le pasan podría ser se verifica en el tiempo de ejecución y causa una falla en el tiempo de compilación, lo que mejora en gran medida la seguridad.
Por último, todos los parámetros variados se escriben y se pueden verificar en tiempo de compilación al igual que se verifican los parámetros no variados.
En algunos casos de uso, sería deseable tener tipos alternativos, como cuando se escribe una función para almacenar claves y valores en una colección. Esto también podría tener cabida simplemente permitiendo más parámetros formales después de la elipsis, al igual que
void store (collection dict, ... int counter, key_t key, val_t value);
Esta función podría entonces ser llamado como
store(dict, key1, val1, key2, val2, key3, val3);
pero serían compilados como si hubiera sido escrito
store(dict, 3, key1, val1, key2, val2, key3, val3);
Los tipos de parámetros reales serían el tiempo de compilación contrastado con los parámetros variadic formales.
Dentro del cuerpo de la función del contador de nuevo se hace referencia por su identificador, claves y valores sería referenciado como si fueran arrays,
key[i]
se refiere a la clave de la clave/valor par i-ésimo value[i]
se refiere al valor del par de valores i-ésimo
y estas referencias se compilarán en sus respectivas direcciones en el marco de la pila.
Nada de esto es realmente difícil de hacer, ni lo ha sido alguna vez. Sin embargo, la filosofía de diseño de C simplemente no favorece dichas características.
Sin un implementador de aventurarse compilador de C (o C implementador preprocesador) tomar la iniciativa para poner en práctica este o un esquema similar es poco probable que alguna vez vimos nada de este tipo en C
El problema es que la gente que están interesados en la seguridad de tipo y están dispuestos a poner en el trabajo para construir sus propios compiladores generalmente llegan a la conclusión de que el lenguaje C está más allá de salvamento y uno puede comenzar de nuevo con un lenguaje mejor diseñado para empezar.
He estado allí, finalmente decidí abandonar el intento, luego implementé uno de los idiomas de Wirth y agregué el tipo de variantes seguras a eso en su lugar. Desde entonces me encontré con otras personas que me contaron sobre sus propios intentos abortados. Las variantes seguras de tipo adecuado en C parecen estar a punto de seguir siendo difíciles de alcanzar.
Si todos los tipos deben ser del mismo tipo, ¿ha considerado pasar una serie de ellos? –
Ninguna matriz nativa en C89. No se puede pasar, por ejemplo, 'f ({1,2,3,0})' con el compilador MS C. – mikebloch
¿quieres algo que funcione con gcc o MS C? Por favor marque apropiadamente. Con C99 hay soluciones que son seguras en cuanto a tipo de letra. –