Page 1 of 1

Unlimited Arguments

Posted: Wed Nov 02, 2005 5:20 pm
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;
}

Re:Unlimited Arguments

Posted: Wed Nov 02, 2005 6:08 pm
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).

Re:Unlimited Arguments

Posted: Wed Nov 02, 2005 7:45 pm
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));
}

Re:Unlimited Arguments

Posted: Wed Nov 02, 2005 8:22 pm
by C-Coder
so i need a ftoa() function, does gcc or g++, libc have one ?

Re:Unlimited Arguments

Posted: Wed Nov 02, 2005 9:34 pm
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);
}

Re:Unlimited Arguments

Posted: Wed Nov 02, 2005 9:53 pm
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

Re:Unlimited Arguments

Posted: Wed Nov 02, 2005 10:10 pm
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.

Re:Unlimited Arguments

Posted: Wed Nov 02, 2005 11:27 pm
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

Re:Unlimited Arguments

Posted: Wed Nov 02, 2005 11:32 pm
by C-Coder
sorry AR
it also worked on tcc, i forgot to include stdarg.h
thanks again AR

Re:Unlimited Arguments

Posted: Thu Nov 03, 2005 3:34 pm
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.

Re:Unlimited Arguments

Posted: Sun Nov 06, 2005 5:41 pm
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.

Re:Unlimited Arguments

Posted: Sun Nov 06, 2005 5:44 pm
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));
}