📄 invvarargs.19930307.html
字号:
<html><!-- Mirrored from c-faq.com/varargs/invvarargs.19930307.html by HTTrack Website Copier/3.x [XR&CO'2008], Sat, 14 Mar 2009 08:03:09 GMT --><head><title>"inverse varargs problem", take 4</title></head><body>[This message was originally sent on March 7, 1993,to someone who asked about the "wacky ideas".]<p>From: scs@adam.mit.edu (Steve Summit)<br>Subject: Re: dynamic function call<br>Date: Sun, 7 Mar 93 17:58:52 -0500<br>Message-Id: <9303072258.AA22973@adam.MIT.EDU><p>You wrote:<br>> I was curious to find out your ideas on the below question appearing<br>> in the C language FAQ:<br>><br>> 7.5: How can I call a function with an argument list built up at run<br>> time?<br>><br>> A: There is no guaranteed or portable way to do this. If you're<br>> curious, ask this list's editor, who has a few wacky ideas you<br>> could try... (See also question 16.10.)<br><a href="invvarargs.html">[current version of this question, now numbered 15.13]</a><p>Believe it or not, you're the first to have asked, so you get tobe the first to hear me apologize for the fact that severalelaborate discussions of those "wacky ideas" which I've writtenat various times are in fact stuck off in my magtape archivessomewhere, not readily accessible.<br>[The two main ones I was probably thinking of are<a href="invvarargs.19890604.html">this one</a>and<a href="invvarargs.19920714.html">this one</a>.]<p>Here is an outline; I'll try to find one of my longer olddescriptions and send it later.<p>The basic idea is to postulate the existence of the followingroutine:<p><pre><TT> #include <stdarg.h> callg(funcp, argp) int (*funcp)(); magic_arglist_pointer argp;</TT></pre><p>This routine calls the function pointed to by <TT>funcp</TT>, passing toit the argument list pointed to by <TT>argp</TT>. It returns whatever thepointed-to function returns.<p>The second question is of course how to construct the argumentlist pointed to by <TT>argp</TT>. I've had a number of ideas over theyears on how to do this; perhaps the best (or at least the oneI'm currently happiest with) is to do something like this:<p><pre><TT> extern func(); va_alloc(arglist, 10); va_list argp; va_start2(arglist, argp); va_arg(argp, int) = 1; va_arg(argp, double) = 2.3; va_arg(argp, char *) = "four"; va_finish2(arglist, argp); callg(func, arglist);</TT></pre><p>The above is equivalent to the simple call<p><pre><TT> func(1, 2.3, "four");</TT></pre><p>Now, the interesting thing is that it's often (perhaps even"usually") possible to construct <TT>va_alloc</TT>, <TT>va_start2</TT>, and<TT>va_finish2</TT> macros such as I've illustrated above such that thestandard <TT>va_arg</TT> macro out of <TT><stdarg.h></TT> or <TT><varargs.h></TT> does thereal work. (In other words, the traditional implementations of<TT>va_arg</TT> would in fact work in an lvalue context, i.e. on the lefthand side of an assignment.)<p>I'm fairly sure I've got working versions of macros along thelines of <TT>va_alloc</TT>, <TT>va_start2</TT>, and <TT>va_finish2</TT> macros somewhere,but I can't find them at the moment, either. At the <a href="#end">end of thismessage</a> I'll append a <a href="varargs2.h">different set of macros</a>, not predicated onthe assumption of being able to re-use the existing <TT>va_arg</TT> on theleft hand side, which should serve as an example of the essentialimplementation ideas.<p>A third question is what to do if the return type (not just theargument list) of the called function is not known at compiletime. (If you're still with me, we're moving in the direction ofdoing so much at run time that we've practically stoppedcompiling and started interpreting, and in fact many of the ideasI'm discussing in this note come out of my attempts to write afull-blown C interpreter.) We can answer the third question byadding a third argument to our hypothetical <TT>callg()</TT> routine,involving a tag describing the type of result we expect and aunion in which any return value can be stored.<p>A fourth question is how to write this hypothetical <TT>callg()</TT>function. It is one of my favorite examples of a function thatessentially must be written in assembler, not for efficiency, butbecause it's something you simply can't do in C. It's actuallynot terribly hard to write; I've got implementations of it formost of the machines I use. I write it for a new environment bycompiling a simple little program fragment such as<p><pre><TT> int nargs; int args[10]; int (*funcp)(); int i; switch(nargs) { case 0: (*funcp)(); break; case 1: (*funcp)(args[0]); break; case 2: (*funcp)(args[0], args[1]); break; ... for(i = 0; i < nargs; i++) (*funcp)(args[i]);</TT></pre><p>, and massaging the assembly language output to push a variablenumber of arguments before performing the (single) call. It'spossible to do this without knowing very much else about theassembly/machine language in use. (It helps a lot to have acompiler output or listing option which lets you see the itsgenerated assembly language.)<p>When I say it's generally easy to write <TT>callg</TT>, I'm thinking ofconventional, stack-based machines. Some modern machines passsome or all arguments in registers, and which registers are usedcan depend on the type of the arguments, which makes this sort ofthing much harder.<p>A fifth question is where my name "callg" comes from. The VAX has asingle instruction, CALLG, which does exactly what you want here. (In other words, an assembly-language implementation of this<TT>callg()</TT> routine is a single line of assembler on the VAX.)I've also used the name <TT>va_call</TT> instead of <TT>callg</TT>.<p>If you have questions or comments prompted by any of this, or ifyou'd like to see more code fragments, feel free to ask.<p><address><a href="http://www.eskimo.com/~scs/">Steve Summit</a><br><a href="mailto:scs@eskimo.com">scs@eskimo.com</a></address><p><a name="end">[The aforementioned "set of macros" is in this file:<a href="varargs2.h">varargs2.h</a> .]</body><!-- Mirrored from c-faq.com/varargs/invvarargs.19930307.html by HTTrack Website Copier/3.x [XR&CO'2008], Sat, 14 Mar 2009 08:03:12 GMT --></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -