2011-08-23 15 views
5

Estoy jugando con la pila y los parámetros de llamada de la función. Lo que quiero lograr aquí es obtener el valor de los parámetros variables directamente utilizando la pila.Obtener argumentos variables directamente desde la pila

Funciona (o parece que funciona) bien cuando no uso parámetros variables. Esto es lo que está funcionando:

void test(int a, int b) 
{ 
    unsigned char *ptr; 
    int i; 

    ptr = (unsigned char*)&a; 
    for (i = 0; i < 4; i++) 
    { 
     printf("%d,", *ptr); 
    }  
} 

que funciona, que puede recuperar el valor de b; El mismo código utilizando

void test(int a, ...); 

como el prototipo de la función no funciona.

No puedo entender lo que está pasando aquí.

¿Me puede ayudar? Gracias!

Edit: Ok, entonces ve que no hay una manera estable y confiable de hacer ese tipo de cosas por mi cuenta. Digamos que en la función de llamada, conozco el tamaño de los datos (pero no el tipo) del argumento de la variable, ¿hay alguna forma de captarlos?

+4

Lo que está haciendo es un comportamiento indefinido. ¿Qué estás intentando lograr? –

+1

¿Cómo intentas obtener los argumentos variables? Sugerencia: stdargs.h, va_start, va_arg, va_end. – arunkumar

+0

@jweyric: estoy usando gcc. Sé que podría usar va_ * macro, pero eso es puramente expiremental, solo estoy intentando cosas para saber cómo funciona: P – Xaqq

Respuesta

1

En las funciones con ... puede utilizar va_ * macro

void test(int a, ...) { 
    va_list ap; 
    va_start(ap, a); 
    // Your code 
    va_end(ap);  
} 
2

Como siempre que se sepa o se puede determinar el número de argumentos, puede utilizar las macros de <stdarg.h>:

#include <stdio.h> 
#include <stdarg.h> 

void test1(int n, ...) 
{ 
    va_list args; 
    va_start(args, n); 
    for (int i = 0; i < n; i++) 
    { 
     int j = va_arg(args, int); 
     printf("%d: %d\n", i, j); 
    } 
    va_end(args); 
} 

void test2(int a, ...) 
{ 
    va_list args; 
    int i = 0; 
    printf("%d: %d\n", i++, a); 
    va_start(args, a); 
    int j; 
    while ((j = va_arg(args, int)) > 0) 
     printf("%d: %d\n", i++, j); 
    va_end(args); 
} 

La diferencia está en cómo se llaman estas dos funciones:

int main(void) 
{ 
    test1(4, 1, 3, 7, 9); 
    test2(1, 3, 7, 9, 0); 
    return(0); 
} 

LaLa familiausa una técnica alternativa pero equivalente; esas funciones escanean la cadena de formato y determinan el tipo de cada argumento (así como el número de argumentos) de la información en la cadena de formato. Por lo tanto, sus principales opciones son:

  • recuento - test1()
  • centinela - test2()
  • formato de cadena - printf()
+0

El problema con su respuesta es que está asumiendo que el argumento es de tipo int.En mi caso, conocer el tipo de mi argumento no es una opción. Conozco los números y el tamaño de los mismos. ¿Cómo puedo tratarlos como datos binarios en bruto? ¿Hay alguna manera de hacer algo como "data = va_arg (ap, get_size_from_somewhere()); Eso sería muy útil porque podría almacenar esos datos tal como están. – Xaqq

+0

Idea: Podría construir mis datos sin formato usando int, bucle con va_arg() para my_data_size/4 + 1 iteraciones. Pero entonces, ¿qué pasa con la alineación de la memoria o el argumento que tiene un tamaño de 1 o 2 bytes? – Xaqq

+0

Si no sabe, o no puede deducir, el tipo de las variables en el pila, estás atascado. No puedes declarar una variable local para mantener los parámetros, todo lo demás aparte. Si conoces los tipos, puedes hacerlo; asumí una lista homogénea de enteros porque era conveniente. es decir, el código de llamada debe proporcionar suficiente información a la función llamada que la función llamada conoce el número y tipo (e indirectamente el tamaño) o cada parámetro representado por puntos suspensivos ('' ... ''). No tengo idea de qué te refieres a "datos binarios en bruto", tratándolos como uniformemente "int" hace ese. –

Cuestiones relacionadas