Path: utzoo!utgpu!attcan!uunet!husc6!uwvax!umn-d-ub!nic.MR.NET!tank!mimsy!chris From: chris@mimsy.UUCP (Chris Torek) Newsgroups: comp.lang.c Subject: Re: Passing types to a subroutine Message-ID: <14461@mimsy.UUCP> Date: 10 Nov 88 11:29:28 GMT References: <14457@mimsy.UUCP> Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 101 In article <14457@mimsy.UUCP> sjr@mimsy.UUCP (Stephen J. Roznowski) writes: >I'm in the process of developing a piece of code that needs >to be portable across several different machines. What I >need to do is something of the following: [edited] > subroutine(...., , ...); > subroutine(...., , ...); > >and have the subroutine do the right thing with a[]. >How do you pass the knowledge of the array type to the >subroutine? I need to be able to pass the knowledge >that the array a[] is either float or double (or for >that matter unsign int). This is easy: you cannot do it at all in C. The best approximation is something like this: float a[100]; subroutine(TYPE_FLOAT, a, (double *)NULL); ... double a[100]; subroutine(TYPE_DOUBLE, (float *)NULL, a); ... subroutine(t, iffloat, ifdouble) enum whichtype t; float *iffloat; double *ifdouble; { double x; switch (t) { case TYPE_FLOAT: if (iffloat == NULL || ifdouble != NULL) panic("subroutine TYPE_FLOAT"); break; case TYPE_DOUBLE: if (iffloat != NULL || ifdouble == NULL) panic("subroutine TYPE_DOUBLE"); break; } ... x = t == TYPE_FLOAT ? iffloat[subscript] : ifdouble[subscript]; ... } It should be obvious that the prefix type argument is unnecessary, being easily computed by which argument is not NULL; in this example it serves as a double-check. If the subroutine in question is (or is in) the innermost loop of the code, it will probably pay to write as many different versions of it as you have types. One technique for doing this without actually duplicating the code (leading to errors of the form `I forgot to update one') is to use the C preprocessor: /* * make sub_float(), which is subroutine() of flavour `float'. */ #define sub_flavour sub_float #define type_flavour float #include "subroutine.c" #undef sub_flavour #undef type_flavour /* * make sub_double(), which is the same, but `double'. */ #define sub_flavour sub_double #define type_flavour double #include "subroutine.c" #undef sub_flavour #undef type_flavour /* * make sub_unsigned(). */ #define sub_flavour sub_unsigned #define type_flavour unsigned #include "subroutine.c" #undef sub_flavour #undef type_flavour subroutine.c starts out like this: sub_flavour(this, that, arr, the_other) type_flavour *arr; { } -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris