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.