help with a 'C' problemR

Blair P. Houghton bhoughto at pima.intel.com
Mon Jun 24 16:02:33 AEST 1991


In article <1991Jun23.235734.11392 at chinacat.unicom.com> woody at chinacat.unicom.com (Woody Baker @ Eagle Signal) writes:
>struct FILE
>	{
>       ...
>	struct fileops
>		{
>		int (*fread_c)();	/* read a character routine */
>		int (*fwrite_c)();	/* write a character routine */
>		int (*unkn)();
>		...
>		} *f_ops;
>	};
>and a pointer to it
>struct FILE *fp;
>how would one go about the following?
>	1. calling the functions f_ops[0], i.e. the 
>	file read function.

Like so:

	int i;				/* integer to catch return value */

	i = (fp->f_ops->fread_c)();

The `()' operator has unspecified precedence wrt the `->' operator,
hence the parentheses around the calling expression.

Note:  This assumes you've assigned `fp->f_ops' to point to an
existing `struct fileops' object (the declaration above only
declares what a `struct fileops' is, it doesn't create one)
and set each pointer to point to an elsewhere-defined function.

>	2. Reading the address of the function  fread_c from the FILE struct

`fread_c' is the identifier of a member of the struct, not the
name of a function.  The value stored in `fp->f_ops->fread_c' is
the address of the function.  If you want the address of the structure
member `fread_c':

	int (**addr)();		/* addr is ptr to ptr to funct returning int */

	addr = &(fp->f_ops->fread_c);	/* parentheses are optional here */

>	3. Altering the address of the function fread_c from the FILE struct.

Say you've defined a function named `actual_function' like this:

	int actual_function ( ... )
	{
	/* code that (at the least) causes return of an int */
	}

And the declaration of `actual_function' is in scope (i.e.,
using an `extern' declaration (possibly a prototype), or
the function-definition itself, earlier in the file); then
you'd assign its address to the structure like this:

	fp->f_ops->fread_c = actual_function;	/* sort of like an array name */

or

	fp->f_ops->fread_c = &actual_function;	/* redundant addressof */

>in 68000 code, I am trying to generate code that is equivalent to the
>following fragment

Questionable move.  If you want specific object code, you
should code in assembler.  That said, this might just work
(especially if you optimize).

>perhaps the  struct fileops should be better constructed to be an
>array?

This would gain you nothing, and would cost you since you
now have to maintain (at the least) documentation
associating array indices with function mnemonics, while
the structure member names can be listed in the table of
contents.  An array of pointers to compatible objects
should have the same size and alignment as a structure
holding the same number of the same kind of pointers.

Also, you may have your structure defined wrongly for this;
you seem to want the `FILE' structure to contain all of the
pointers to functions, rather than point to the `struct
fileops' that contains the pointers.  To do so, declare
`f_ops' without the asterisk, then refer to `fread_c' like
so (using the examples above):

	i = (fp->f_ops.fread_c)();		/* call */

	fp->f_ops.fread_c = actual_function;	/* assignment */

	addr = &(fp->f_ops.fread_c);		/* address of struct member */
	*addr = actual_function;		/* alternative assignment */
	i = (*addr)();				/* alternative call */

>Please reply via e-mail, as my time is rather limited (60 min/day)
>on my usenet node, and I don't have time to comb through the 'C' newsgroup.

Oh, great.  Now you tell me...

				--Blair
				  "Damn it.  I'm posting, anyway."



More information about the Comp.unix.wizards mailing list