Xaqq
Xaqq

Reputation: 4386

Get variable arguments directly from stack

I'm playing with the stack and function's call parameters. What I want to achieve here is to get the value of variable parameters directly using the stack.

It works (or seems to work) fine when I don't use variable parameters. Here is what is working:

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

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

That works, I can retrieve the value of b; The same code using

void test(int a, ...);

as function's prototype doesn't work.

I cant understand what's going on here.

Can you help me? Thanks !

Edit: Ok, then it seeems there is no stable and reliable way to do that kind of stuff on my own. Lets say that in the callee function I know the data size (but not the type) of variable argument, is there a way to grab them ?

Upvotes: 5

Views: 444

Answers (2)

Jonathan Leffler
Jonathan Leffler

Reputation: 754090

As long as you know or can determine the number of arguments, you can use the macros from <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);
}

The difference is in how these two functions are called:

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

The printf() family uses an alternative but equivalent technique; those functions scan the format string and determine the type of each argument (as well as the number of arguments) from the information in the format string. So, your main options are:

  • count - test1()
  • sentinel - test2()
  • format string - printf()

Upvotes: 2

vromanov
vromanov

Reputation: 919

In functions with ... you can use va_* macro

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

Upvotes: 1

Related Questions