Unlimited Arguments

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
C-Coder

Unlimited Arguments

Post by C-Coder »

hi guys
i want to get the parameters of a function with unlimited arguments
here is my code, it worked but i get warnings :

arg.c:6: warning: return type defaults to `int'
arg.c: In function `main':
arg.c:8: warning: control reaches end of non-void function
arg.c: In function `myfunc':
arg.c:13: warning: initialization makes pointer from integer without a cast
arg.c:14: warning: assignment makes pointer from integer without a cast
arg.c:15: warning: assignment makes pointer from integer without a cast
arg.c:16: warning: assignment makes pointer from integer without a cast

any one have a better solution ? or solve me these warnings

Code: Select all

#include <stdio.h>
void myfunc(char *, ...);
int get_param(int, int);

main()
{
  myfunc("hi how are you", 5, 6);
}

void myfunc(char *str, ...)
{
  int *d1,*d2,*d3;
  int *address=(int)&str;
  d1=(int)get_param(0, (int)*address);
  d2=(int)get_param(1, (int) address);
  d3=(int)get_param(2, (int) address);
  printf("%s\n", (char *)d1);
  printf("%d\n", (int)*d2);
  printf("%d\n", (int)*d3);
}

int get_param(int n, int addr)
{
  int address;
  address=(addr)+(n*4);
  return address;
}
User avatar
kataklinger
Member
Member
Posts: 381
Joined: Fri Nov 04, 2005 12:00 am
Location: Serbia

Re:Unlimited Arguments

Post by kataklinger »

For the first and for the secon on you should add "return 0;" at the end of main(), or define main as "void main()", because default return type is int not void. And for the rest you should do (int*) casting not (int).
C-Coder

Re:Unlimited Arguments

Post by C-Coder »

My latest code worked, but it didn't print the floating numbers !
What should i do in order to make my code print the floating numbers ?

Code: Select all

#include <stdio.h>
void myfunc(char *, ...);
int get_param(int, char *);


int main()
{
  myfunc("hi how are you", 5, 6, 'H', -118.625);
  return 0;
}

void myfunc(char *str, ...)
{
  char *d0,*d1,*d2,*d3,*d4;
  d0=str;
  d1=(char *)get_param(1, (char *)&str);
  d2=(char *)get_param(2, (char *)&str);
  d3=(char *)get_param(3, (char *)&str);
  d4=(char *)get_param(4, (char *)&str);
  printf("1st Argument: %s\n", d0);
  printf("2nd Argument: %d\n", (int)*d1);
  printf("3rd Argument: %d\n", (int)*d2);
  printf("4th Argument: %c\n", (char)*d3);
  printf("5th Argument: %f\n", (float)*d4);
 }

int get_param(int n, char *addr)
{
   return (int)((addr)+(n*4));
}
C-Coder

Re:Unlimited Arguments

Post by C-Coder »

so i need a ftoa() function, does gcc or g++, libc have one ?
AR

Re:Unlimited Arguments

Post by AR »

Using GCC builtins:

Code: Select all

void myfunc(char *format, ...)
{
    __builtin_va_list va;
    __builtin_va_start(va, format);

    printf("1st Argument: %s\n", __builtin_va_arg(va, char*));
    printf("2nd Argument: %d\n", __builtin_va_arg(va, int));
    printf("3rd Argument: %d\n", __builtin_va_arg(va, int));
    printf("4th Argument: %c\n", __builtin_va_arg(va, int));
    printf("5th Argument: %f\n", __builtin_va_arg(va, float));

    __builtin_va_end(va);
}
C-Coder

Re:Unlimited Arguments

Post by C-Coder »

ya i knew about that but i was afraid of compatability with other c compilers,

Code: Select all

    printf("5th Argument: %f\n", __builtin_va_arg(va, float));
should changed to

Code: Select all

    printf("5th Argument: %f\n", __builtin_va_arg(va, double));
gcc reserves space for float as double (64-bit) and char as int (32-bit) in the unlimited arguments (...)

This code gives segmentation fault:

Code: Select all

    printf("1st Argument: %s\n", __builtin_va_arg(va, char*));
thanks very much AR
AR

Re:Unlimited Arguments

Post by AR »

The first line seg faults cause it was meant to be:

Code: Select all

printf("1st Argument: %s\n", str);
There is some complex macro you can use but I prefer:

Code: Select all

#include <stdarg.h>
int myfunc(char *str, ...)
{
    va_list va;
    va_start(va, str);
    ...
    va_end(va);
}
stdarg is part of the freestanding environment for GCC and assumably other compilers as well.
C-Coder

Re:Unlimited Arguments

Post by C-Coder »

yup that works ;)
thanks AR
but why the traditional way i used (using pointer) don't work for float ?
another thing, not all compilers support __builtin_va_list, this code ofcourse worked on gcc but failed on tinycc.
thanks again AR
C-Coder

Re:Unlimited Arguments

Post by C-Coder »

sorry AR
it also worked on tcc, i forgot to include stdarg.h
thanks again AR
nick8325
Member
Member
Posts: 200
Joined: Wed Oct 18, 2006 5:49 am

Re:Unlimited Arguments

Post by nick8325 »

C-Coder wrote: but why the traditional way i used (using pointer) don't work for float ?
I think there is a mistake in your code:

Code: Select all

(float)*d4
should be

Code: Select all

*(float *)d4
.

The first works out *d4 - which is a char - and turns it into a float. Since chars are only one byte long and floats are (on x86, normally) four, that's not what you want.

The second turns d4 into a pointer to float, and then works out the value of the actual float at the location.

By the way, the code you've written is the same sort of thing that will happen internally in va_arg. But va_arg is processor-specific and does a few more things - for example, a double on x86 is 8 bytes long, so if get_param(n, addr) is the address of the float, the next variable will be at get_param(n+2, addr). va_arg (which is normally a macro) will look at the size of the type to decide how much to skip. There are also alignment problems...but it is not really very different.
C-Coder

Re:Unlimited Arguments

Post by C-Coder »

nick8325 wrote:
C-Coder wrote: but why the traditional way i used (using pointer) don't work for float ?
I think there is a mistake in your code:

Code: Select all

(float)*d4
should be

Code: Select all

*(float *)d4
ya thanks, it worked but it should be

Code: Select all

*(double *)d4
gcc manual says that gcc reserve 64-bit for float when passed through (...)
so in unlimited arguments the float == double && char == int in the reserved space.
C-Coder

Re:Unlimited Arguments

Post by C-Coder »

So the latest working version of code is:

Code: Select all

#include <stdio.h>
void myfunc(char *, ...);
int get_param(int, char *);


int main()
{
  myfunc("hi how are you", 5, 6, 'H', -118.625);
  return 0;
}

void myfunc(char *str, ...)
{
  char *d0,*d1,*d2,*d3,*d4;
  d0=str;
  d1=(char *)get_param(1, (char *)&str);
  d2=(char *)get_param(2, (char *)&str);
  d3=(char *)get_param(3, (char *)&str);
  d4=(char *)get_param(4, (char *)&str);
  printf("1st Argument: %s\n", d0);
  printf("2nd Argument: %d\n", *(int *)d1);
  printf("3rd Argument: %d\n", *(int *)d2);
  printf("4th Argument: %c\n", *(int *)d3);
  printf("5th Argument: %f\n", *(double *)d4);
}

int get_param(int n, char *addr)
{
  return (int)((addr)+(n*4));
}
Post Reply