473,795 Members | 3,279 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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 3850
In article <sl************ ******@poly.0ls en.net>
Clint Olsen <cl***@0lsen.ne t> 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.0ls en.net>
Clint Olsen <cl***@0lsen.ne t> 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**********@y ahoo.com> writes:
On Mon, 27 Oct 2003 02:36:07 -0700, Chris Torek wrote:
In article <sl************ ******@poly.0ls en.net>
Clint Olsen <cl***@0lsen.ne t> 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**********@y ahoo.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**********@y ahoo.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
16292
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
12393
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
2194
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 call the methods with, what the properties return etc. Does it have to be a .net dll? Thanks!
15
4023
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
10750
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 as a valid return value for the typeof operator in a later version of ECMAScript or is this a JScript "feature"? -- Klaus Johannes Rusch
1
3185
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). The README file in the Tools/freeze directory of the Python-2.4.4 distribution says the following (and many other things): Previous versions of Freeze used a pretty simple-minded algorithm to
13
2144
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." ); return 0; }
0
2196
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): frame = inspect.currentframe() try: function = inspect.getframeinfo(getframe)
0
9672
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9519
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10435
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
7538
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6779
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5563
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4113
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3721
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2920
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.