Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   function casts (http://www.velocityreviews.com/forums/t953308-function-casts.html)

BartC 10-12-2012 09:42 PM

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


Alan Curry 10-12-2012 10:11 PM

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

BartC 10-12-2012 10:19 PM

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



BartC 10-12-2012 10:27 PM

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


Ian Collins 10-12-2012 10:29 PM

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

BartC 10-13-2012 12:37 AM

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


Les Cargill 10-13-2012 02:37 AM

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

BartC 10-13-2012 11:48 AM

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


Ben Bacarisse 10-13-2012 12:23 PM

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.

88888 Dihedral 10-13-2012 01:46 PM

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.