Получить переменные аргументы напрямую из стека - PullRequest
5 голосов
/ 24 августа 2011

Я играю со стеком и параметрами вызова функции. Здесь я хочу получить значение переменных параметров напрямую, используя стек.

Это работает (или, кажется, работает) нормально, когда я не использую переменные параметры. Вот что работает:

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

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

Это работает, я могу получить значение b; Тот же код, используя

void test(int a, ...);

как прототип функции не работает.

Я не могу понять, что здесь происходит.

Вы можете мне помочь? Спасибо!

Edit: Хорошо, тогда кажется, что не существует стабильного и надежного способа делать подобные вещи самостоятельно. Допустим, в функции callee я знаю размер (но не тип) аргумента переменной, есть ли способ получить их?

Ответы [ 2 ]

2 голосов
/ 24 августа 2011

Пока вы знаете или можете определить количество аргументов, вы можете использовать макросы из <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);
}

Разница в том, как эти две функции называются:

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

Семейство printf() использует альтернативную, но эквивалентную технику; Эти функции сканируют строку формата и определяют тип каждого аргумента (а также количество аргументов) из информации в строке формата. Итак, ваши основные варианты:

  • count - test1()
  • Страж - test2()
  • строка формата - printf()
1 голос
/ 24 августа 2011

В функциях с ... вы можете использовать va_ * macro

void test(int a, ...) {
  va_list ap;
  va_start(ap, a);
  // Your code
  va_end(ap);    
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...