Path: utzoo!utgpu!watmath!att!pacbell!ames!excelan!ames!dftsrv!mimsy!chris From: chris@mimsy.UUCP (Chris Torek) Newsgroups: comp.lang.c Subject: Re: on the fringe of C syntax/semantics Message-ID: <19971@mimsy.UUCP> Date: 4 Oct 89 08:02:39 GMT References: <80100001@bonzo> Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 66 In article <80100001@bonzo> roy@bonzo.sts.COM writes: >Here are a couple questions that come up in conjunction with using the >'varargs' series of function calls. When calling the va_arg() >function, the 2nd parameter is supposed to be simply a type .... va_arg is not a function. va_arg is a macro or (in some compilers) a `magic cookie' (in ANSI-conformant compilers, once the ANSI C standard is a standard, va_arg will have to be a macro that is defined as a magic cookie in these compilers). >... how does it know what type you specified? The usual definition of va_arg for conventional stack machines is something like #define va_arg(ap, type) (((type *)(ap += sizeof(type)))[-1]) Note in particular that the `type' argument must produce a new type when suffixed with `*', so that `int' and `double' are legal, but `void (*)(void)' is not. >The second question is in conjunction with how to declare certain types. >Things like 'int' and 'char *' are a piece of cake, but how about a good, >general declaration for a function? If you are trying to write `ANSI C' (which, again, does not yet exist; we are all just assuming that it will work the way the proposed standard describes), the short answer is `there is none'. Every function pointer, however, `fits in' every other function pointer, so you can obtain a `pointer to function of no arguments returning int' and then cast it to `pointer to function of one ``char *'' argument returning int' and then call through the result: foo(sometype firstarg, ...) { /* * A typedef is required so that we can append `*' to * get `pointer to pointer to function (args) returning ...' */ typedef int (*fn)(void); fn x; va_list ap; int first = 1; va_start(ap, firstarg); for (;;) { x = va_arg(ap, fn); if (x == NULL) break; if (first) { ((int (*)(sometype))fn)(firstarg); first = 0; } else fn(); } va_end(ap); } If all the `fn's will have the same (fixed) set of arguments, you can simply typedef int (*fn)(type1, type2, type3); and leave out all the casts. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris