una tipos tablas tabla que procedimiento funciones funcion escalares ejecutar devuelven devolver datos almacenado c parameters command-line-arguments declaration function-declaration

tipos - que es una funcion en sql



¿Qué ocurre si declaro una función con una tabla de parámetros vacía y luego le paso argumentos? (2)

Por ejemplo,

#include <stdio.h> void foo(); int main(void) { foo(); foo(42); foo("a string", ''C'', 1.0); return 0; } void foo() { puts("foo() is called"); }

Salida:

foo() is called foo() is called foo() is called

Este código compila bien (sin advertencias usando clang) y funciona bien. Pero me pregunto qué pasará con los valores pasados ​​a foo() ? ¿Los empujan hacia la pila o simplemente los descartan?

Quizás esta pregunta parezca inútil, pero tiene sentido. Por ejemplo, cuando tengo int main() , en lugar de int main(void) , y le paso algunos argumentos de línea de comando, ¿se verá afectado el comportamiento de main() ?

Además, cuando se usa <stdarg.h> , se requiere al menos un parámetro con nombre antes ... por ISO C. ¿Es posible que podamos hacer uso de declaraciones como void foo() para pasar de cero a argumentos infinitos a un ¿función?

Noté que void foo() es una "declaración no prototipo" y que void foo(void) es una "declaración de prototipo" justo ahora. ¿Es esto algo relevante?

Aclaración

Parece que esta pregunta está marcada como duplicada en ¿Qué significa una lista de parámetros vacía? [duplicado] (Curiosamente, esa pregunta también está duplicada ...). De hecho, no creo que mi pregunta tenga nada que ver con eso. Se enfoca en "What void foo() significa en C", pero sé que esto significa que "puedo pasarle cualquier cantidad de argumentos", y también sé que es una característica obsoleta.

Pero esta pregunta es bastante diferente. La palabra clave es "Qué pasaría si". Solo quiero saber si paso diferentes cantidades de argumentos a void foo() , al igual que el código de ejemplo anterior, ¿pueden usarse dentro de foo() ? Si es así, ¿cómo se hace? Si no, ¿los argumentos pasados ​​hacen alguna diferencia? Esa es mi pregunta.


En C, void foo() declara una función que toma un número no especificado de parámetros. Una función se declara de la siguiente manera:

return-type function-name(parameter-list,...) { body... }

parameter-list es la lista de parámetros que la función toma separados por comas. Si no se proporcionan parámetros, la función no toma ninguno y debe definirse con un conjunto vacío de paréntesis o con la palabra clave void. Si ningún tipo de variable está delante de una variable en la lista de parámetros, entonces se supone int.


Como dijo Jonathan Leffler, la convención de llamadas de C establece que la función de llamada (no la llamada) es responsable de extraer argumentos de la pila, por lo que el programa no se bloqueará incluso si los argumentos no coinciden con lo que espera la función llamada.

Añadiré que la convención de llamadas de C también establece que los argumentos se insertan en la pila en orden inverso (es decir, la llamada foo (1, 2) empuja a los 2 luego a 1 ). Esto permite que la función llamada tenga acceso a los primeros parámetros, incluso si no conoce el resto. Por ejemplo, una función declarada int foo (int a, int b, ...) podrá acceder a y b incluso sin saber qué otros parámetros se han pasado: a y b están justo en la parte superior de la pila. Acceder a otros argumentos requeriría hacks de punteros de pila, que es exactamente lo que printf hace. Por supuesto, uno puede obtener resultados divertidos usando diferentes argumentos de lo que se espera (por ejemplo, printf ("%d%d", 3.5); ).

Entonces, según la pregunta, sí, int foo () se puede llamar de forma segura con cualquier número / tipo de argumentos, y en la década de 1980 se consideraría una "práctica normal" utilizar los piratas punteros en la pila para acceder a parámetros desconocidos. Cuando la portabilidad y la legibilidad se convirtieron en una preocupación cada vez mayor, <stdarg.h> apareció como una forma portátil de implementar estos <stdarg.h> (el compilador generará el código correcto para la plataforma objetivo, por lo que ya no es un "hack") . Sin embargo, como se ha dicho, <stdarg.h> requiere al menos un parámetro, por lo que no puede ayudar con int foo () .