function casts

Discussion in 'C Programming' started by BartC, Oct 12, 2012.

  1. BartC

    BartC Guest

    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
     
    BartC, Oct 12, 2012
    #1
    1. Advertising

  2. BartC

    Alan Curry Guest

    In article <k5a2tp$kkj$>, BartC <> 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
     
    Alan Curry, Oct 12, 2012
    #2
    1. Advertising

  3. BartC

    BartC Guest

    "Scott Fluhrer" <> wrote in message
    news:1350079266.477728@rcdn-nntpcache-3...
    >
    > "BartC" <> wrote in message
    > news:k5a2tp$kkj$...


    >> 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, Oct 12, 2012
    #3
  4. BartC

    BartC Guest

    "Alan Curry" <> wrote in message
    news:k5a4ic$baq$...

    >> ((*(*()))())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
     
    BartC, Oct 12, 2012
    #4
  5. BartC

    Ian Collins Guest

    On 10/13/12 11:19, BartC wrote:
    >
    > "Scott Fluhrer"<> wrote in message
    > news:1350079266.477728@rcdn-nntpcache-3...
    >>
    >> "BartC"<> wrote in message
    >> news:k5a2tp$kkj$...

    >
    >>> 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
     
    Ian Collins, Oct 12, 2012
    #5
  6. BartC

    BartC Guest

    "Ian Collins" <> wrote in message
    news:...
    > 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
     
    BartC, Oct 13, 2012
    #6
  7. BartC

    Les Cargill Guest

    BartC wrote:
    > "Ian Collins" <> wrote in message
    > news:...
    >> 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
     
    Les Cargill, Oct 13, 2012
    #7
  8. BartC

    BartC Guest

    "Les Cargill" <> wrote in message
    news:k5ajp5$c73$...
    > 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
     
    BartC, Oct 13, 2012
    #8
  9. "BartC" <> writes:

    > "Les Cargill" <> wrote in message
    > news:k5ajp5$c73$...
    >> 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.
     
    Ben Bacarisse, Oct 13, 2012
    #9
  10. 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.
     
    88888 Dihedral, Oct 13, 2012
    #10
  11. BartC

    BartC Guest

    "Ben Bacarisse" <> wrote in message
    news:...
    > "BartC" <> writes:


    >> 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.


    It originally targeted ASM, so I guess it's a compiler. Maybe I could
    generate C from the AST instead of intermediate code, and it might be
    possible to create more structured C that way than the 'flat' C I'm creating
    now. But I don't think that would solve too many of my current problems, and
    would probably create new ones!

    > 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.


    My pointers are typed, but I just use byte offsets which are more flexible.
    As an example of the type issues I have to deal with in C, take this program
    in my source language (to do with the function casts I was asking about).
    Not C-like, but hopefully clear:

    ref int pcptr

    proc disploop=
    ref ref proc() fnptr @ pcptr

    do
    fnptr^^()
    od
    end

    This is the C code generated (in the above code, fnptr and pcptr are the
    same memory location, that needs to be emulated in C):

    static void disploop(void);
    static int (*pcptr);

    void disploop(void) {
    /* void (*(*fnptr)) (void) @pcptr */

    L2:
    (*((void (*(*)) (void))pcptr))();
    goto L2;
    }

    And this is the x86 code that I might generate instead, just the function
    body:

    disploop:
    L3:
    mov esi,[pcptr]
    mov eax,[esi]
    call eax
    jmp L3
    retn

    Notice this doesn't involve asterisks, parentheses or voids that have to be
    in exactly the right pattern! Although the generated C could have been
    tidied up a bit, I don't see how this stuff can be avoided, no matter how
    the C is generated.

    > 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.


    Maybe. Some problems can solved by writing wrapper functions *in C*. But I'm
    trying to avoid that (you can't tell someone using the language and trying
    to call an imported C function, to switch to another language!). As a silly
    example, take this program in my source language:

    stop

    which is translated to a call to a runtime function, also in the source
    language, which happens to call the imported C function exit(). However
    'exit' is a reserved word in my language! So I call a wrapper function in C,
    which calls exit() for me.

    --
    Bartc
     
    BartC, Oct 13, 2012
    #11
  12. BartC

    Les Cargill Guest

    BartC wrote:
    > "Les Cargill" <> wrote in message
    > news:k5ajp5$c73$...
    >> 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!)).
    >


    So that's not *NEARLY* stupid enough :) By "Think Stupid", I mean
    vastly reduce the number of degrees of freedom for the generated code.

    > C is fussy about type-matching pointers (so T* and U* don't match); the
    > source language doesn't care.
    >


    Generally, I store (void *) pointers in a table, then have a column in
    the table that suggests a type.

    > 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.)
    >


    Could be, then. I mean no disrespect, but it sounds like you're
    doing it the Hard Way, which is ... hard.

    > (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!
    >


    *Shrug?*

    struct Thing[] = {
    { (void *)&X, (void *)&Y, "op", (void *)&Z },
    ....
    };

    void eval(Thing *t)
    {
    ....
    }

    ....

    eval(&Thing[0]);

    ....


    --
    Les Cargill
     
    Les Cargill, Oct 13, 2012
    #12
  13. BartC

    BartC Guest

    "Les Cargill" <> wrote in message
    news:k5ck02$tsk$...
    > BartC wrote:


    >> C also does pointer arithmetic using object-sized offsets, while the
    >> source
    >> language uses byte offsets! Generating dumb ASM code is actually far
    >> easier.


    > Could be, then. I mean no disrespect, but it sounds like you're
    > doing it the Hard Way, which is ... hard.


    What, always using byte offsets for pointers? It's very useful. What's hard
    about it is that C works differently.

    (Perhaps I should explain I'm using dynamic language A for this project,
    which compiles source code of a static language B, into C source code. I
    hardly write any actual C at all; mainly when I find myself editing the C
    output files by mistake.)

    >> 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!


    > struct Thing[] = {
    > { (void *)&X, (void *)&Y, "op", (void *)&Z },
    > ...
    > };


    OK, that's a *bit* like my intermediate code (my operands can be more
    elaborate and have type info attached to each. But it is a faithful
    representation of what the source HLL is trying to do).

    > void eval(Thing *t)
    > {
    > ...
    > }
    >
    > ...
    >
    > eval(&Thing[0]);


    Here I'm not sure what's happening. Does this code reside in a compiler (and
    the Thing array has been filled in by the compiler)? Then the eval() routine
    presumably writes out some C code into a separate file. In which case it's
    not that different to what I'm actually doing. (And it's the tiny details
    that are the problem: endless compile errors on the C output code, due to
    some subtleties of the C type system that I have no interest in yet have to
    understand and fix!)

    Or is some kind of interpretation going on?

    --
    Bartc
     
    BartC, Oct 13, 2012
    #13
  14. "BartC" <> writes:
    > "Les Cargill" <> wrote in message
    > news:k5ck02$tsk$...
    >> BartC wrote:

    >
    >>> C also does pointer arithmetic using object-sized offsets, while the
    >>> source
    >>> language uses byte offsets! Generating dumb ASM code is actually far
    >>> easier.

    >
    >> Could be, then. I mean no disrespect, but it sounds like you're
    >> doing it the Hard Way, which is ... hard.

    >
    > What, always using byte offsets for pointers? It's very useful. What's hard
    > about it is that C works differently.


    C pointers of type `unsigned char*` work *exactly* like that.

    [...]

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Oct 13, 2012
    #14
  15. BartC

    BartC Guest

    "Keith Thompson" <> wrote in message
    news:...
    > "BartC" <> writes:


    >> What, always using byte offsets for pointers? It's very useful. What's
    >> hard
    >> about it is that C works differently.

    >
    > C pointers of type `unsigned char*` work *exactly* like that.


    Yes, I know, that's why I'm using lots of casts to (unsigned char*).

    But in general, a pointer will have a stride of N bytes. It's not always
    clear if that can be used directly (because the pointer might be unaligned,
    and/or the offset could be odd).

    --
    Bartc
     
    BartC, Oct 14, 2012
    #15
  16. BartC

    Ian Collins Guest

    On 10/14/12 12:16, BartC wrote:
    >
    >
    > "Keith Thompson"<> wrote in message
    > news:...
    >> "BartC"<> writes:

    >
    >>> What, always using byte offsets for pointers? It's very useful. What's
    >>> hard
    >>> about it is that C works differently.

    >>
    >> C pointers of type `unsigned char*` work *exactly* like that.

    >
    > Yes, I know, that's why I'm using lots of casts to (unsigned char*).


    Why cast at all? Do everything with unsigned char*.

    --
    Ian Collins
     
    Ian Collins, Oct 14, 2012
    #16
  17. BartC

    Les Cargill Guest

    BartC wrote:
    > "Les Cargill" <> wrote in message
    > news:k5ck02$tsk$...
    >> BartC wrote:

    >
    >>> C also does pointer arithmetic using object-sized offsets, while the
    >>> source
    >>> language uses byte offsets! Generating dumb ASM code is actually far
    >>> easier.

    >
    >> Could be, then. I mean no disrespect, but it sounds like you're
    >> doing it the Hard Way, which is ... hard.

    >
    > What, always using byte offsets for pointers? It's very useful. What's hard
    > about it is that C works differently.
    >
    > (Perhaps I should explain I'm using dynamic language A for this project,
    > which compiles source code of a static language B, into C source code. I
    > hardly write any actual C at all; mainly when I find myself editing the
    > C output files by mistake.)
    >
    >>> 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!

    >
    >> struct Thing[] = {
    >> { (void *)&X, (void *)&Y, "op", (void *)&Z },
    >> ...
    >> };

    >
    > OK, that's a *bit* like my intermediate code (my operands can be more
    > elaborate and have type info attached to each. But it is a faithful
    > representation of what the source HLL is trying to do).
    >
    >> void eval(Thing *t)
    >> {
    >> ...
    >> }
    >>
    >> ...
    >>
    >> eval(&Thing[0]);

    >
    > Here I'm not sure what's happening. Does this code reside in a compiler
    > (and
    > the Thing array has been filled in by the compiler)?


    The Thing array is what has been generated. eval is handwritten.

    >Then the eval()
    > routine
    > presumably writes out some C code into a separate file. In which case it's
    > not that different to what I'm actually doing. (And it's the tiny details
    > that are the problem: endless compile errors on the C output code, due to
    > some subtleties of the C type system that I have no interest in yet have to
    > understand and fix!)
    >
    > Or is some kind of interpretation going on?


    Basically - yes. You stick values into an array, then use an
    interpreter ( eval(...) )to exploit the array.

    >

    --
    Les Cargill
     
    Les Cargill, Oct 14, 2012
    #17
  18. "BartC" <> writes:
    > "Keith Thompson" <> wrote in message
    > news:...
    >> "BartC" <> writes:

    >
    >>> What, always using byte offsets for pointers? It's very useful. What's
    >>> hard
    >>> about it is that C works differently.

    >>
    >> C pointers of type `unsigned char*` work *exactly* like that.

    >
    > Yes, I know, that's why I'm using lots of casts to (unsigned char*).


    Why not just use pointers of type `unsigned char*` in the first place?

    [...]

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Oct 14, 2012
    #18
  19. BartC

    BartC Guest

    "Keith Thompson" <> wrote in message
    news:...
    > "BartC" <> writes:
    >> "Keith Thompson" <> wrote in message
    >> news:...
    >>> "BartC" <> writes:

    >>
    >>>> What, always using byte offsets for pointers? It's very useful. What's
    >>>> hard
    >>>> about it is that C works differently.
    >>>
    >>> C pointers of type `unsigned char*` work *exactly* like that.

    >>
    >> Yes, I know, that's why I'm using lots of casts to (unsigned char*).

    >
    > Why not just use pointers of type `unsigned char*` in the first place?


    This subthread is about the use of C as target language for a translator
    from another language.

    Pointers to all kinds of types will crop up everywhere, but particularly
    where a direct C idiom (a->b, c etc) can't be used. Then these casts are
    necessary. (And once pointer expressions are used in some places, then it's
    often easier to just use them everywhere rather than investigate which could
    use a->b, c etc)

    For example, the other language might have a C-like struct data-type, but
    with the ability to have extra unofficial fields defined by a type and a
    byte offset from the start:

    typedef struct _s {
    float a,b,c,d;
    } S;

    S s;

    Suppose this struct has another unofficial field 'x' of type int at byte
    offset 12. To access this field in s, the expression:

    *(&s+12)

    can't be used; &S is a pointer to a struct (of stride perhaps 16 bytes), and
    will point far outside the struct. Instead, if the offset is a multiple of
    sizeof(int), the following could be used:

    *((int*)&s+3)

    If the offset was 10 instead (sometimes unaligned accesses are fine; or
    perhaps s could itself be misaligned by 2 bytes), then this is impossible in
    C without using byte offsets somewhere:

    *((int*)((char*)&s+10))

    (Most uses of these 'unofficial' fields, ie. those which redefine, shadow or
    alias existing fields, could be represented in C by anonymous unions and
    structs. Such unions and structs are available using gcc. However they are
    still implemented in the source language by byte offsets.

    Where x in the above example is at offset 12, then an official (gcc)
    definition might be:

    typedef struct _s {
    float a,b
    union (float c; int x;};
    float d;
    } S;

    Where x is at offset 10, then it's a bit more fiddly:

    #pragma pack(1)
    typedef struct _s {
    union {
    struct {float a,b,c,d;};
    struct {char dummy[10]; int x};
    };
    } S;

    You can see that just using a byte offset might be simplest!)

    --
    Bartc
     
    BartC, Oct 14, 2012
    #19
  20. "BartC" <> writes:

    > "Keith Thompson" <> wrote in message
    > news:...
    >> "BartC" <> writes:
    >>> "Keith Thompson" <> wrote in message
    >>> news:...
    >>>> "BartC" <> writes:
    >>>
    >>>>> What, always using byte offsets for pointers? It's very useful. What's
    >>>>> hard
    >>>>> about it is that C works differently.
    >>>>
    >>>> C pointers of type `unsigned char*` work *exactly* like that.
    >>>
    >>> Yes, I know, that's why I'm using lots of casts to (unsigned char*).

    >>
    >> Why not just use pointers of type `unsigned char*` in the first place?

    >
    > This subthread is about the use of C as target language for a translator
    > from another language.
    >
    > Pointers to all kinds of types will crop up everywhere, but particularly
    > where a direct C idiom (a->b, c etc) can't be used. Then these casts are
    > necessary. (And once pointer expressions are used in some places, then it's
    > often easier to just use them everywhere rather than investigate which could
    > use a->b, c etc)
    >
    > For example, the other language might have a C-like struct data-type, but
    > with the ability to have extra unofficial fields defined by a type and a
    > byte offset from the start:
    >
    > typedef struct _s {
    > float a,b,c,d;
    > } S;
    >
    > S s;
    >
    > Suppose this struct has another unofficial field 'x' of type int at byte
    > offset 12. To access this field in s, the expression:
    >
    > *(&s+12)
    >
    > can't be used; &S is a pointer to a struct (of stride perhaps 16 bytes), and
    > will point far outside the struct.


    Why are there structs here at all? I think that's the point that's been
    made elsewhere ("be dumb, not smart") and what I was getting at by
    saying that it looks more like a translator than a compiler.

    In an assembler-generating compiler there wouldd be no structs and there
    don't have to be in C either. _s could be a char (well, unsigned char)
    array of the right size. Just as you have to tell the assembler what
    size object to load from an address, you would have to do the same in
    the generated C, so while _s + 12 is now the right address you still
    have to say how much to fetch (*(int *)(s + 12)) but it's probably
    closer to the model you compiler seems to have been using before.

    I suspect that you want the benefit of some C typing (so you don't have
    to worry about the size of objects for example) but that's causing
    problems elsewhere because the compiler's model is still based round the
    raw machine picture that assembler gives you.

    <snip>
    > You can see that just using a byte offset might be simplest!)


    Yes, and byte pointers (unsigned char *s) to go with them!

    --
    Ben.
     
    Ben Bacarisse, Oct 14, 2012
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?Q2hyaXMgRGF2b2xp?=

    Web casts in ASP.Net

    =?Utf-8?B?Q2hyaXMgRGF2b2xp?=, Oct 19, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    528
    clintonG
    Oct 19, 2005
  2. cgbusch
    Replies:
    2
    Views:
    349
    Sudsy
    Jul 8, 2003
  3. Joona I Palaste

    Needless casts?

    Joona I Palaste, Apr 24, 2004, in forum: Java
    Replies:
    15
    Views:
    715
    Icemerth
    Apr 25, 2004
  4. Dan Upton

    checking casts

    Dan Upton, Nov 29, 2005, in forum: Java
    Replies:
    4
    Views:
    763
    Chris Smith
    Dec 1, 2005
  5. Replies:
    13
    Views:
    585
    Alf P. Steinbach
    Jan 19, 2007
Loading...

Share This Page