![]() |
function casts
Suppose I have a pointer to pointer to function like this:
void (*(*fnptr)) (void); How do I apply this function signature as a cast to another type, say the variable p here: int *p; and call the result? (So I want to pretend p is the same type as fnptr, and I want to call it. I've already figured out that calling fnptr is done as (*(*fnptr))().) I'm getting lost in silly parentheses at the moment; my last attempt was: ((*(*()))())p(); -- Bartc |
Re: function casts
In article <k5a2tp$kkj$1@dont-email.me>, BartC <bc@freeuk.com> wrote:
>Suppose I have a pointer to pointer to function like this: > > void (*(*fnptr)) (void); The inner parentheses aren't doing anything, unless they are making the mess more readable to you. > >How do I apply this function signature as a cast to another type, say the >variable p here: > > int *p; > >and call the result? (So I want to pretend p is the same type as fnptr, and >I want to call it. I've already figured out that calling fnptr is done as >(*(*fnptr))().) > >I'm getting lost in silly parentheses at the moment; my last attempt was: > > ((*(*()))())p(); Where did the voids go? You might be able to get away with leaving out the function parameters, but when casting to something involving a function pointer, the function return type has to be in there somewhere. The cast itself is (void(**)(void))p (Rule: take your declaration of fnptr, remove the word "fnptr" from it, and stick it in an outer set of parentheses which are the cast syntax) After that, dereference with * once to get the function pointer from the pointer-to-function-pointer, and then you can call it, by parenthesizing the whole thing for precedence purposes and adding the () containing the arguments (in this case none). Full example program: #include <stdio.h> static void f1(void) { printf("Hello, "); } static void f2(void) { printf("world!\n"); } int main(void) { void (*fnp) (void); /* pointer to function */ void (**fnptr) (void); /* pointer to pointer to function */ int *p; fnp = f1; fnptr = &fnp; p = (int *)fnptr; (*(void(**)(void))p)(); fnp = f2; /* fnptr = &fnp */ /* unchanged from before */ /* p = (int *)fnptr; */ /* unchanged from before */ (*(void(**)(void))p)(); return 0; } -- Alan Curry |
Re: function casts
"Scott Fluhrer" <sfluhrer@ix.netcom.com> wrote in message news:1350079266.477728@rcdn-nntpcache-3... > > "BartC" <bc@freeuk.com> wrote in message > news:k5a2tp$kkj$1@dont-email.me... >> void (*(*fnptr)) (void); >> >> How do I apply this function signature as a cast to another type, say the >> variable p here: >> >> int *p; >> >> and call the result? > Even if you get the parens in all the right places, well, if it's hard to > write, it'll be hard to read. That's not important; I'm using a code generator, and the result will only be seen by a C compiler (unless it doesn't work). > In cases like this, typedef is your friend: > typedef void (*f_ptr) (void); > > (*(f_ptr*)p)(); Thanks. I managed to incorporate that typedef into the cast, and it now works! (*(void(**)(void))p)(); (I should have noticed there were a couple of voids missing.) Now I just have to persuade my code generator to do it automatically.. -- Bartc |
Re: function casts
"Alan Curry" <pacman@kosh.dhis.org> wrote in message news:k5a4ic$baq$1@speranza.aioe.org... >> ((*(*()))())p(); > > Where did the voids go? You might be able to get away with leaving out the > function parameters, but when casting to something involving a function > pointer, the function return type has to be in there somewhere. I've no idea how I ended up with the above. It's possible I was just trying things at random! > The cast itself is (void(**)(void))p OK, thanks. I've now got that (and stored it somewhere safe too just in case). > (Rule: take your declaration of fnptr, remove the word "fnptr" from it, > and > stick it in an outer set of parentheses which are the cast syntax) Will do.. -- Bartc |
Re: function casts
On 10/13/12 11:19, BartC wrote:
> > "Scott Fluhrer"<sfluhrer@ix.netcom.com> wrote in message > news:1350079266.477728@rcdn-nntpcache-3... >> >> "BartC"<bc@freeuk.com> wrote in message >> news:k5a2tp$kkj$1@dont-email.me... > >>> void (*(*fnptr)) (void); >>> >>> How do I apply this function signature as a cast to another type, say the >>> variable p here: >>> >>> int *p; >>> >>> and call the result? > >> Even if you get the parens in all the right places, well, if it's hard to >> write, it'll be hard to read. > > That's not important; I'm using a code generator, and the result will only > be seen by a C compiler (unless it doesn't work). I write a lot of code generators and I always try an generate code that is close to indistinguishable from my had written code. I find it makes me think more about what I write. Doing so would certainly have helped you in this case! -- Ian Collins |
Re: function casts
"Ian Collins" <ian-news@hotmail.com> wrote in message
news:adrjuqFrq4rU1@mid.individual.net... > On 10/13/12 11:19, BartC wrote: >> That's not important; I'm using a code generator, and the result will >> only >> be seen by a C compiler (unless it doesn't work). > > I write a lot of code generators and I always try an generate code that is > close to indistinguishable from my had written code. I find it makes me > think more about what I write. Doing so would certainly have helped you > in this case! My case is probably a little different, as I'm starting from a somewhat different language, and translating to C source code (this is for a compiler targeting C). It's been a struggle, as the two languages don't match exactly, neither is C anywhere near the 'portable assembler' that everyone says it is. Nearly every single aspect of C 'gets in the way'; the type declaration syntax is a minor issue! I can't make use of half the language (most of the control statements are out for example), and the output is terrible-looking, completely unstructured C. (Fortunately gcc seems to tidy up the result very well and the eventual code is faster than if I'd generated ASM directly, but ASM is anyway not practical at the minute.) -- Bartc |
Re: function casts
BartC wrote:
> "Ian Collins" <ian-news@hotmail.com> wrote in message > news:adrjuqFrq4rU1@mid.individual.net... >> On 10/13/12 11:19, BartC wrote: > >>> That's not important; I'm using a code generator, and the result will >>> only >>> be seen by a C compiler (unless it doesn't work). >> >> I write a lot of code generators and I always try an generate code >> that is close to indistinguishable from my had written code. I find >> it makes me think more about what I write. Doing so would certainly >> have helped you in this case! > > My case is probably a little different, as I'm starting from a somewhat > different language, and translating to C source code (this is for a > compiler targeting C). > > It's been a struggle, as the two languages don't match exactly, neither > is C anywhere near the 'portable assembler' that everyone says it is. Dunno - 'C' makes a pretty good target language, but you have to Think Stupid. > Nearly every single aspect of C 'gets in the way'; the type declaration > syntax is a minor issue! > > I can't make use of half the language (most of the control statements > are out for example), and the output is terrible-looking, completely > unstructured C. (Fortunately gcc seems to tidy up the result very well > and the eventual code is faster than if I'd generated ASM directly, but > ASM is anyway not practical at the minute.) > The best way to generate 'C' is to generate tables that hand-coded 'C' then operates on. Tables can include callbacks... -- Les Cargill |
Re: function casts
"Les Cargill" <lcargill99@comcast.com> wrote in message
news:k5ajp5$c73$1@dont-email.me... > BartC wrote: >> It's been a struggle, as the two languages don't match exactly, neither >> is C anywhere near the 'portable assembler' that everyone says it is. > > Dunno - 'C' makes a pretty good target language, but you have to Think > Stupid. I can't; C insists on very strict type-checking, so I have to double guess what C expects the type of any expression to be, and compare that with the original types, and any coercions, of the source language. Then you may have to apply extra coercions which work differently on l-values, &-terms and *-terms. And there's the quirk where A usually means the value of A, *unless* it's an array then it means &A[0] (in the source language, arrays have values (as well as having arbitrary lower bounds for good measure!)). C is fussy about type-matching pointers (so T* and U* don't match); the source language doesn't care. C also does pointer arithmetic using object-sized offsets, while the source language uses byte offsets! Generating dumb ASM code is actually far easier. (What's much harder is generating efficient, optimised ASM.) (There are many other issues: for example C is case-sensitive, the source language isn't; trying to import a C function such as fopen() into the source language, without also importing the FILE* type; words that are identifiers in one language but reserved words in the other, etc etc.) >> I can't make use of half the language (most of the control statements >> are out for example), and the output is terrible-looking, completely >> unstructured C. > The best way to generate 'C' is to > generate tables that hand-coded 'C' then operates on. > Tables can include callbacks... My starting point is intermediate code, a '3-address-code' kind of representation. At this point everything is already linearised and unstructured, as the usual target is assembly code. You then translate each instruction into a simple C statement, typically an assignment of the form X = Y op Z; It sounds easy; it isn't! -- Bartc |
Re: function casts
"BartC" <bc@freeuk.com> writes:
> "Les Cargill" <lcargill99@comcast.com> wrote in message > news:k5ajp5$c73$1@dont-email.me... >> BartC wrote: > >>> It's been a struggle, as the two languages don't match exactly, neither >>> is C anywhere near the 'portable assembler' that everyone says it is. >> >> Dunno - 'C' makes a pretty good target language, but you have to Think >> Stupid. > > I can't; C insists on very strict type-checking, so I have to double guess > what C expects the type of any expression to be, and compare that with the > original types, and any coercions, of the source language. > > Then you may have to apply extra coercions which work differently on > l-values, &-terms and *-terms. And there's the quirk where A usually means > the value of A, *unless* it's an array then it means &A[0] (in the source > language, arrays have values (as well as having arbitrary lower bounds for > good measure!)). > > C is fussy about type-matching pointers (so T* and U* don't match); the > source language doesn't care. > > C also does pointer arithmetic using object-sized offsets, while the source > language uses byte offsets! Generating dumb ASM code is actually far easier. > (What's much harder is generating efficient, optimised ASM.) This point and the last one suggest that you are generating code at what I'd be tempted to call the wrong level. I.e. rather than a compiler it sounds like a translator. If your source language pointers are type agnostic and use bytes offsets, I'd expect them all to appear as unsigned char pointer in the C output. C's rules for pointer compatibility and arithmetic won't then come into it. > (There are many other issues: for example C is case-sensitive, the source > language isn't; trying to import a C function such as fopen() into the > source language, without also importing the FILE* type; words that are > identifiers in one language but reserved words in the other, etc etc.) Surely all your source-language names are kept in a separate space? You can then use an "escape" convention to capture case: source name func maps to srcfunc__ and Func to, say, src_func__. I can't see how a reserved word can be a problem unless you are trying to some sort of minimal source-level translation rather than what would be more normally termed compilation. If, on the other hand, you've decided that C functions should be callable with no wrappers at all, then I think you've just made a rod for your own back. <snip> > It sounds easy; it isn't! Yes, I'm not saying that it is, but I think you may have designed things to be harder than they need to be. -- Ben. |
Re: function casts
Bart於 2012年10月13日星期*UTC+8上午5時43分22 寫道:
> Suppose I have a pointer to pointer to function like this: > > > > void (*(*fnptr)) (void); > > > > How do I apply this function signature as a cast to another type, say the > > variable p here: > > > > int *p; > > > > and call the result? (So I want to pretend p is the same type as fnptr, and > > I want to call it. I've already figured out that calling fnptr is done as > > (*(*fnptr))().) > > > > I'm getting lost in silly parentheses at the moment; my last attempt was: > > > > ((*(*()))())p(); > > > > -- > > Bartc I think the use of functon pointers are well documented in C90. I use initializers for setting up funtors that could return handles to emulate the functional programming in LISP 10 years ago. |
| All times are GMT. The time now is 03:47 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.