Passing types to a subroutine

Chris Torek chris at mimsy.UUCP
Thu Nov 10 21:29:28 AEST 1988


In article <14457 at mimsy.UUCP> sjr at 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(...., <float array>, ...);
>	subroutine(...., <double array>, ...);
>
>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)
		<types for this, that>
		type_flavour *arr;
		<type for the_other>
	{
		<code>
	}
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris at mimsy.umd.edu	Path:	uunet!mimsy!chris



More information about the Comp.lang.c mailing list