[comp.unix.wizards] help with a 'C' problemR

bhoughto@pima.intel.com (Blair P. Houghton) (06/24/91)

In article <1991Jun23.235734.11392@chinacat.unicom.com> woody@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."

torek@elf.ee.lbl.gov (Chris Torek) (06/26/91)

In article <4825@inews.intel.com> bhoughto@pima.intel.com (Blair P. Houghton)
writes:
>	i = (fp->f_ops->fread_c)();
>The `()' operator has unspecified precedence wrt the `->' operator,
>hence the parentheses around the calling expression.

Minor correction: it is not `unspecified'; the expression

	fp->f_ops->fread_c()

must parse as

	(((fp)->f_ops)->f_read)()

`Classic C' compilers may require an indirection first; since function call
binds more tightly than indirection, you must write

	(*fp->f_ops->fread_c)()

in this case.
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov

jim@segue.segue.com (Jim Balter) (06/26/91)

In article <4825@inews.intel.com> bhoughto@pima.intel.com (Blair P. Houghton) writes:
>The `()' operator has unspecified precedence wrt the `->' operator,

Sez who?  a->b() is unambiguous, certainly according to ANSI.
a->(b()) is obviously meaningless in C (it could mean something in a language
with names as datatypes, such as LISP).

bhoughto@bishop.intel.com (Blair P. Houghton) (06/27/91)

In article <7980@segue.segue.com> jim@segue.segue.com (Jim Balter) writes:
>In article <4825@inews.intel.com> bhoughto@pima.intel.com (Blair P. Houghton) writes:
>>The `()' operator has unspecified precedence wrt the `->' operator,

Ok, ok, explicitly, true; implicitly, false; it's all
deducible from the allowable types of operands; and, for
some reason I thought I'd typed "ambiguous" instead of
"unspecified" and left the "ambiguous" dangling in ambiguous
erroneousness...

>Sez who?  a->b() is unambiguous, certainly according to ANSI.
>a->(b()) is obviously meaningless in C (it could mean something in a language
>with names as datatypes, such as LISP).

#define lingus() angus

    feargus = seamus->(lingus());

				--Blair
				  "Okay, so it's bogus..."

gwyn@smoke.brl.mil (Doug Gwyn) (06/27/91)

In article <4878@inews.intel.com> bhoughto@bishop.intel.com (Blair P. Houghton) writes:
>>>The `()' operator has unspecified precedence wrt the `->' operator,
>Ok, ok, explicitly, true; implicitly, false; it's all
>deducible from the allowable types of operands; ...

Not only is this not a UNIX Wizardly topic, but it's not even C wizardly.
The production rule "postfix-expression: postfix-expression -> identifier"
in conjunction with "postfix-expression: postfix-expression ( argument-
expression-list )" specifies how to parse p->f().  This is neither
unspecified nor ambiguous.