LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 05-27-2013, 02:28 PM   #1
zagzagel
Member
 
Registered: Jul 2010
Location: Portugal
Distribution: Arch Linux
Posts: 31

Rep: Reputation: 1
what is the printf equivalent to pass values by ref? (C programming)


I need to do something like this:

Code:
int main(....) {
    double actual_data[] = { 1., 2., 3. };
    FILE *fp = stdout;

    /* print the stuff */
    /* ordinary printf */
    /* fprintf(fp, "%lf\n", actual_data[1]); */
    /* how i want to print */
    function_whose_name_i_want_to_know(fp, "%lf\n", &actual_data[1]);
    
}
I actually have a void ** in my code, but this explains what I want. The function knows the size of the argument from the format string, so it's not much different from printf.
 
Old 05-27-2013, 03:08 PM   #2
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
I don't think exactly what you are asking for exists.
vfprintf is close.
 
Old 05-27-2013, 05:43 PM   #3
zagzagel
Member
 
Registered: Jul 2010
Location: Portugal
Distribution: Arch Linux
Posts: 31

Original Poster
Rep: Reputation: 1
Doesn't really suit my needs. The input data is also by value. I do have the ability to preprocess the arguments, but I have to typecast them manually, which implies parsing the format specifier, and I don't feel like reinventing printf, and also constructing some va_list, which I'm not even sure that it generates well-defined behaviour.

I need to print an undefined data type (void * to an array of elements) knowing the size of each element and format to printf them. In the above example I would have
Code:
void *data = actual_data;
int sizeofelements = sizeof(double);
char *format = "%lf";
/* print_based_on_above_info */
?...?
Can anyone think of an idea?
 
Old 05-27-2013, 10:11 PM   #4
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Quote:
Originally Posted by zagzagel View Post
I need to print an undefined data type (void * to an array of elements) knowing the size of each element and format to printf them.
Do you mean the format specifier and element size are parameters that may vary at runtime?

I think you will be stuck reinventing printf.
 
Old 05-28-2013, 09:58 AM   #5
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,862
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
Sadly, as far as I know, there is no standardized way to create a variadic parameter-list...
 
Old 05-28-2013, 11:00 AM   #6
H_TeXMeX_H
LQ Guru
 
Registered: Oct 2005
Location: $RANDOM
Distribution: slackware64
Posts: 12,928
Blog Entries: 2

Rep: Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301
Can't you just write a loop and print them out one by one ?
 
Old 05-29-2013, 04:48 AM   #7
zagzagel
Member
 
Registered: Jul 2010
Location: Portugal
Distribution: Arch Linux
Posts: 31

Original Poster
Rep: Reputation: 1
Huh... always thought there had to be a way. If we look at it printf has no more information than that (unless I misread 'man stdarg'). It is still required to provide a type to va_arg().

@H_TeXMeX_H: What loop? I can't even print one of them :P their type changes at runtime. My final goal involves a loop, yes, but the void* might be double, char, int, foo, or any combination of all. At run-time.

Guess I'll have to do specialized functions, or maybe I'll try C11's Type-generic expressions, though I'm not fond of recent standards.

Thanks for the answears.
 
Old 05-29-2013, 07:21 AM   #8
H_TeXMeX_H
LQ Guru
 
Registered: Oct 2005
Location: $RANDOM
Distribution: slackware64
Posts: 12,928
Blog Entries: 2

Rep: Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301
Maybe you need an interpreted language ... maybe Perl.

If not, then you would have to try and detect the type and do different things based upon it. It's not a trivial task what you ask for.
 
Old 05-29-2013, 07:46 AM   #9
mina86
Member
 
Registered: Aug 2008
Distribution: Debian
Posts: 517

Rep: Reputation: 229Reputation: 229Reputation: 229
Quote:
Originally Posted by NevemTeve View Post
Sadly, as far as I know, there is no standardized way to create a variadic parameter-list...
Uh? What about va_start, va_arg, va_end and va_copy macros?

zagzagel, if I understand your problem correctly than unfortunately yes, you'll have to “reinvent” printf even thought you won't have to fully interpret the format specifier. However, you may encounter some other issues. You see, your “%lf” specifier is actually not valid. You should use “%f” for both floats and doubles since the former gets promoted to the latter when passed as … argument. (Similarly, integer types are promoted to at least and int or unsigned int). This means that whereas this is valid:
Code:
float f;
double d;
printf("%f %f\n", f, d); /* both get passed as double */
If you try to use the same format for some other function, you won't have enough information to distinguish between pointer to float and pointer to double:
Code:
float f;
double d;
myprintf("%f %f\n", &f, &d); /* no way to tell float* from double* */
What is it that you actually want to do?
 
Old 05-29-2013, 05:42 PM   #10
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
I think I misunderstand the problem. Is it that you want the print function to dereference the arguments? Why can't they be dereferenced at the time they're passed to the variadic function?

Kevin Barry
 
Old 05-31-2013, 12:16 AM   #11
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,862
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
> > Sadly, as far as I know, there is no standardized way to create a variadic parameter-list...
> Uh? What about va_start, va_arg, va_end and va_copy macros?

Those are to process a variadic parameter-list created by the compiler. There could have been another set of macros like this:

Code:
va_list ap;
va_start_create (ap);
va_add (ap, float, 3.14);
va_add (ap, long long, 20130531LL);
va_end_create (ap);

vprintf ("float=%f, long long=%lld", ap);

Last edited by NevemTeve; 05-31-2013 at 12:17 AM.
 
Old 05-31-2013, 08:26 AM   #12
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
From what I understand, there is no "list"; the values are placed on the stack as with any other function call, and va_arg moves a pointer along the stack based on the argument just before the variadic portion. That's why there needs to be an argument before the variadic portion. I'm sure you could fake a variadic list by placing the values on the stack. You couldn't do so dynamically without some hackery (e.g. alloca,) though.

Kevin Barry
 
Old 05-31-2013, 08:59 AM   #13
H_TeXMeX_H
LQ Guru
 
Registered: Oct 2005
Location: $RANDOM
Distribution: slackware64
Posts: 12,928
Blog Entries: 2

Rep: Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301
The problem is not a variable length parameter list, but rather dealing with types not know until run-time.

Honestly, I think a better description of the exact problem would help solve it.
 
Old 05-31-2013, 09:44 AM   #14
zagzagel
Member
 
Registered: Jul 2010
Location: Portugal
Distribution: Arch Linux
Posts: 31

Original Poster
Rep: Reputation: 1
Quote:
Maybe you need an interpreted language ... maybe Perl.
No can do. This is to embed in an already existing C program.

Quote:
You see, your “%lf” specifier is actually not valid. You should use “%f” for both floats and doubles since the former gets promoted to the latter when passed as … argument.
Didn't know... I never heard the compiler complaining though, and gcc usually complains alot about printf arguments. At least more than I want x)

Quote:
you won't have enough information to distinguish between pointer to float and pointer to double
I will, because I pass the size of arguments as the format. %lf is double, size is known. But seeing as it is not valid, I would have to pass the size of the arguments as an integer as well... That's another bummer.

Quote:
Is it that you want the print function to dereference the arguments?
This is exactly what I want!

Quote:
Why can't they be dereferenced at the time they're passed to the variadic function?
Because they're not know at compile time. They come from void *.

Quote:
Honestly, I think a better description of the exact problem would help solve it.
Maybe so, but I tend to try and solve problems by some means. If I don't know how to program those means, then I ask how to do that. Meanwhile the problem is being solved some other way. In this case it is not, because it was an idea for a friend.
Anyhow, the goal was to print a table in which each cell could have it's own type, and all cells could be passed to a single call that would immediatly print the table (hence the void **)
Kinda like tprint, only that implementation is horrible, each cell has it's own string malloc'ed, and has dedicated functions, and uses glib, etc, etc. My friend planned on just removing the glib dependency, but ended up just keeping the print function, although he wrote in a similar fashion (with the malloc per cell).

The minimum goal was to fill a row or a column all at once and assuming each row/column has the same type. Still to pass it to a single function implied a void *, and the problem persists. Multiple functions to do the same thing seams bad to me. I prefer to maintain a slightly harder function, than to maintain 6 or 7 easier functions.
 
Old 05-31-2013, 10:15 AM   #15
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,862
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
Quote:
Originally Posted by ta0kira
From what I understand, there is no "list"; the values are placed on the stack as with any other function call, and va_arg moves a pointer along the stack based on the argument just before the variadic portion. That's why there needs to be an argument before the variadic portion. I'm sure you could fake a variadic list by placing the values on the stack. You couldn't do so dynamically without some hackery (e.g. alloca,) though.
Good news: it don't have to be alloca-ted, it can be any memory (static, auto, malloc-ed), eg:
Code:
intptr_t mystack[10], *sp= &mystack[0];
*sp++= (intptr_t)'A';
*sp++= (intptr_t)"string";
*sp++= (intptr_t)120L;
*(double *)sp= 3.1415927;
sp += sizeof (double) / sizeof (intptr_t);
...
vprintf ("%c %s %ld %g", (va_list)mystack);
Bad news: this is all wrong. It might work on some platforms, but won't work on others. Example for the latter: gcc, 64bit: va_list isn't just a pointer, it is structure whose members you aren't supposed use (or even know of).
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
grep multiple values in single pass through log file. 1ankit1 Programming 2 11-13-2010 04:45 PM
[SOLVED] udev rules - how to pass ATTRS{*} values to the RUN command? catkin Programming 8 09-26-2010 05:43 AM
gfortran 4.1 equivalent with %val %ref Rexy Programming 0 06-24-2009 06:17 PM
Hiding printf( C programming) outputs from console mendiratta General 3 11-20-2008 03:17 AM
pass arguments and return values from a function in UNIX gaynut Programming 4 07-10-2008 01:56 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 01:04 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration