473,325 Members | 2,860 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,325 software developers and data experts.

Using stdarg with unknown types

I had this crazy idea to use stdarg macros to copy data in a generic
fashion, regardless of type. However, I'm not sure it will work in part
due to the ANSI C default argument promotions and the fact that va_arg
requires a type to decide how far to advance to subsequent arguments. So,
essentially what I want in the variable argument function is something that
just assigns to a character type, and then copy a predefined number of
bytes to a target location (using memcpy or whatever).

Example:

void foo(int numargs, size_t size, ...)

Usage:

/*
* Must use in type due to default argument promotions
*
foo(3, sizeof(int), 'b', 'a', 'r');

or:

/*
* Bar is some defined type and bar1..4 are variables of that type
*
foo(4, sizeof(Bar), bar1, bar2, bar3, bar4);

Any suggestions?

Thanks,

-Clint
Nov 13 '05 #1
6 3801
In article <sl******************@poly.0lsen.net>
Clint Olsen <cl***@0lsen.net> writes:
I had this crazy idea to use stdarg macros to copy data in a generic
fashion, regardless of type. However, I'm not sure it will work in part
due to the ANSI C default argument promotions and the fact that va_arg
requires a type to [examine] ...
Not possible in general. Also, due to ANSI's wacky widening rules,
surprisingly hard to do even in specific, sometimes. :-)
So, essentially what I want in the variable argument function is
something that just assigns to a character type, and then copy a
predefined number of bytes to a target location (using memcpy or
whatever).

Example:

void foo(int numargs, size_t size, ...)

Usage:

/*
* Must use in type due to default argument promotions
*
foo(3, sizeof(int), 'b', 'a', 'r');

or:

/*
* Bar is some defined type and bar1..4 are variables of that type
*
foo(4, sizeof(Bar), bar1, bar2, bar3, bar4);

Any suggestions?


This fails for "typedef float Bar;" on a number of existing
implementations, which pass "int"s in integer registers and
floating-point values in floating-point registers. And of course,
"float"s are widened to "double"s, so just as you had to use
sizeof(int) in the first call, the sizeof(Bar) in the second
produces the wrong number (4 instead of 8).

Even if you fix the latter -- by defining, for instance, a name
for "promoted Bar" -- the former remains a problem. Suppose I
wish to call foo() with some values of type "long" on one of
these machines, which happens to have sizeof(long) == 8. (Note
that sizeof(double) is still 8.) Then:

foo(3, sizeof(long), 0L, 99L, 1L << 53);

passes three "long"s in integer registers -- actually, on at least
one of these machines, only two of them go in the integer registers
and the third is on a stack, but then I have to use "long long" to
make the example fly -- while:

foo(4, sizeof(Promoted_Bar), bar1, bar2, bar3, bar4);

passes the four "double"s in floating-point registers.

Inside foo(), all you have is the number 8. Were the parameters
passed via the integer registers, or in the FPU?

Note that the process gets particularly ugly for narrow types that
might or might not be unsigned and might or might not widen from
(say) 16 to 32 bits, or stay at 32 bits. For instance, suppose
you are using a POSIX header and the type "uid_t". Is uid_t
"unsigned short", or is it a plain short or an int or an unsigned
int? (The answer is different on different hosts; you will find
both results.) If it is unsigned short, and short is 16 bits and
int is 32 bits, it widens to signed int; but if it is unsigned int,
it stays unsigned int. If you needed portability to PDP-11s and
uid_t were unsigned short there, the 16-bit unsigned short would
widen to unsigned int.

(In practice, of course, unsigned and signed "int"s are always
passed the same way on these machines. The integer-vs-FP register
issue also only occurs if you allow floating-point parameters.
Thus, if you are willing to give up broad "pure" portability and
a certain amount of practical functionality, you can get away with
the trick you are aiming for. But at this point you might as well
not write it in C, or at least, not claim that the C is even remotely
portable -- just require a new implementation for each port, and
hope you never come across an un-handle-able situation like the
integer-vs-FP-registers one.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://67.40.109.61/torek/index.html (for the moment)
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 13 '05 #2
On Mon, 27 Oct 2003 02:36:07 -0700, Chris Torek wrote:
In article <sl******************@poly.0lsen.net>
Clint Olsen <cl***@0lsen.net> writes:
I had this crazy idea to use stdarg macros to copy data in a generic
fashion, regardless of type. However, I'm not sure it will work...
Suppose I
wish to call foo() with some values of type "long" on one of these
machines, which happens to have sizeof(long) == 8. Then:

foo(3, sizeof(long), 0L, 99L, 1L << 53);

passes three "long"s in integer registers -- actually, on at least one
of these machines, only two of them go in the integer registers and the
third is on a stack, but then I have to use "long long" to make the
example fly -- while:

foo(4, sizeof(Promoted_Bar), bar1, bar2, bar3, bar4);

passes the four "double"s in floating-point registers.

Inside foo(), all you have is the number 8. Were the parameters passed
via the integer registers, or in the FPU?


I must be missing something. Do the stdarg.h facilities not work
for floating point arguments?
Nov 13 '05 #3
In <pa****************************@yahoo.com> Sheldon Simms <sh**********@yahoo.com> writes:
On Mon, 27 Oct 2003 02:36:07 -0700, Chris Torek wrote:
In article <sl******************@poly.0lsen.net>
Clint Olsen <cl***@0lsen.net> writes:
I had this crazy idea to use stdarg macros to copy data in a generic
fashion, regardless of type. However, I'm not sure it will work...

Suppose I
wish to call foo() with some values of type "long" on one of these
machines, which happens to have sizeof(long) == 8. Then:

foo(3, sizeof(long), 0L, 99L, 1L << 53);

passes three "long"s in integer registers -- actually, on at least one
of these machines, only two of them go in the integer registers and the
third is on a stack, but then I have to use "long long" to make the
example fly -- while:

foo(4, sizeof(Promoted_Bar), bar1, bar2, bar3, bar4);

passes the four "double"s in floating-point registers.

Inside foo(), all you have is the number 8. Were the parameters passed
via the integer registers, or in the FPU?


I must be missing something. Do the stdarg.h facilities not work
for floating point arguments?


They do, but they *know* the argument type, therefore they know where to
look for it: in a GPR, in an FPR or somewhere else.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #4
On 2003-10-27, Chris Torek <no****@elf.eng.bsdi.com> wrote:

Not possible in general. Also, due to ANSI's wacky widening rules,
surprisingly hard to do even in specific, sometimes. :-)


[excellent description of caveats deleted]

Chris:

Thanks a lot for the explanation. It sounds like using void pointers and
memcpy would be the only way to do this portably. It's too bad there's not
a clean(er) way to handle variable argument lists in C...

-Clint
Nov 13 '05 #5
I wrote, in part:
[Assume you are on, e.g., a 64-bit MIPS or SPARC, so that sizeof(long) and sizeof(double) are both 8, while "long"s are
passed in integer registers (a0 through a3 on MIPS, %o0 through
%o5 on SPARC) and "double"s are passed in FPU registers.] Inside [a proposed function] foo(), all you have is the number 8.
Were the parameters passed via the integer registers, or in the FPU?

In article <pa****************************@yahoo.com>,
Sheldon Simms <sh**********@yahoo.com> wrote:I must be missing something. Do the stdarg.h facilities not work
for floating point arguments?


They do -- but compare an actual viable foo1() with the proposed
foo2():

void foo1(const char *fmt, ...) {
va_list ap;

va_start(ap, fmt);
/* as usual the real work is in a v* variant */
vfoo1(fmt, ap);
va_end(ap);
}

void vfoo1(const char *fmt, va_list ap) {
char c;
long l;
double d;

while ((c = *fmt++) != '\0') {
switch (c) {
case 'l':
l = va_arg(ap, long);
... handle long ...
break;
case 'f': case 'd':
d = va_arg(ap, double);
... handle double ...
break;
... more cases here as needed ...
}
}
}

In vfoo1(), we call va_arg() with the name of a type: "int" or
"double". Here is foo2() and the start of vfoo2():

void foo2(int nargs, size_t size, ...) {
va_list ap;

va_start(ap, size);
vfoo2(nargs, size, ap);
va_end(ap);
}

void vfoo2(int nargs, size_t size, va_list ap) {
char c;
long l;
double d;
int argno;

for (argno = 0; argno < nargs; argno++) {
switch (size) {
case 8:
... now what? ...
...
}
}
}

What code would you put under "case 8"?

Note that you can write *either*:

case sizeof(long):

*or*:

case sizeof(double):

instead of the plain "case 8", but using the same number for two
"case"s in a single switch, is a constraint violation, so using
both will produce a compile-time diagnostic (which I suppose is a
good thing here :-) ).
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://67.40.109.61/torek/index.html (for the moment)
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 13 '05 #6
On Tue, 28 Oct 2003 21:36:49 -0700, Chris Torek wrote:
I wrote, in part:
[Assume you are on, e.g., a 64-bit MIPS or SPARC, so that sizeof(long) and sizeof(double) are both 8, while "long"s are
passed in integer registers (a0 through a3 on MIPS, %o0 through
%o5 on SPARC) and "double"s are passed in FPU registers.] Inside [a proposed function] foo(), all you have is the number 8.
Were the parameters passed via the integer registers, or in the FPU?


In article <pa****************************@yahoo.com>,
Sheldon Simms <sh**********@yahoo.com> wrote:
I must be missing something. Do the stdarg.h facilities not work
for floating point arguments?


They do -- but compare an actual viable foo1() with the proposed
foo2():


<rest snipped>

Well I guess it's my turn to feel like an idiot. Hopefully
that will teach me to wait until after the coffee has had its
effect before posting.

Thanks for clarifying...
Nov 13 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

16
by: WittyGuy | last post by:
Hi, What is the major difference between function overloading and function templates? Thanks! http://www.gotw.ca/resources/clcm.htm for info about ]
13
by: Don | last post by:
How do I get an Enum's type using only the Enum name? e.g. Dim enumType as System.Type Dim enumName as String = "MyEnum" enumType = ???(enumName)
3
by: Eric | last post by:
Hi, I wonder if it is possible to import and use an unknown dll in a C# program? I.e. get to know what public variables, methods, properties etc. the dll contains and get to know what parameters to...
15
by: ais523 | last post by:
I was just wondering whether there was a portable way to use gets() safely, and came up with this: #include <stdio.h> #include <stdlib.h> int main() { FILE* temp; char buf;
9
by: Klaus Johannes Rusch | last post by:
IE7 returns "unknown" instead of "undefined" when querying the type of an unknown property of an object, for example document.write(typeof window.missingproperty); Has "unknown" been defined...
1
by: jmalone | last post by:
I have a python script that I need to freeze on AIX 5.1 (customer has AIX and does not want to install Python). The python script is pretty simple (the only things it imports are sys and socket)....
13
by: nariknahom | last post by:
Hi, Can someone tell me what is wrong with the below program? ------------------------------------------- int main() { f1( 25 50,"testing stdarg. ", "it is working", "if it is working." );...
0
by: rajasankar | last post by:
Hi, I am using Jython based application and trying to use inspect.py in the python files. Here is my code import inspect,os,sys,pprint,imp def handle_stackframe_without_leak(getframe): ...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.