[SOLVED] what is the printf equivalent to pass values by ref? (C programming)
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
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.
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
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.
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* */
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?
> > 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);
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.
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.
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:
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).
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.