Como los argumentos se pasan en la pila, va_
"funciones" (la mayoría de las veces se implementan como macros) simplemente manipulan un puntero de pila privada. Este puntero de pila privada se almacena desde el argumento pasado a va_start
, y luego va_arg
"muestra" los argumentos de la "pila" mientras itera los parámetros.
digamos que se llama a la función max
con tres parámetros, así:
max(a, b, c);
Dentro de la función max
, la pila básicamente tiene el siguiente aspecto:
+-----+
| c |
| b |
| a |
| ret |
SP -> +-----+
SP
es el puntero de pila real, , y no es realmente a
, b
y c
que en la pila pero sus valores. ret
es la dirección de retorno, a donde ir cuando se realiza la función.
Lo va_start(ap, n)
hace es tomar la dirección del argumento (n
en su prototipo de función) y desde que calcula la posición del siguiente argumento, por lo que obtener un nuevo puntero de pila privada:
+-----+
| c |
ap -> | b |
| a |
| ret |
SP -> +-----+
Cuando use va_arg(ap, int)
devuelve aquello a lo que apunta el puntero de la pila privada, y luego lo "salta" cambiando el puntero de la pila privada para apuntar ahora al siguiente argumento. La pila ahora se ve así:
+-----+
ap -> | c |
| b |
| a |
| ret |
SP -> +-----+
Esta descripción es, por supuesto, simplificada, pero muestra el principio.
Esto es realmente bastante específico de la plataforma, ya que * muchas * convenciones de llamadas (incluyendo el común x64, PPC, ARM) pasan la mayoría de sus parámetros en los registros. Muchas plataformas no colocan la dirección de retorno en la pila, una o dos plataformas tienen acumulaciones que crecen hacia arriba en lugar de hacia abajo, y algunas convenciones de llamadas colocan argumentos en la pila en el orden opuesto. –
@Skizz: ¡Respuesta impresionante! – Bruce
@DietrichEpp: Lo sé. Pero, con suerte, tiene algunos elementos básicos. Puse algunas notas en la respuesta para reflejar las diversas maneras en que las pilas funcionan. Aún así, cubrir la mayoría de las diferentes formas en que el compilador implementa esto tomaría una respuesta mucho más larga. La forma más sencilla sería encontrar las definiciones de macro y ver que se expanden y, con suerte, no se está produciendo una espeluznante magia de compilación. – Skizz