Re: To execute a string as function

Discussion in 'C Programming' started by Dan Pop, Jun 24, 2003.

  1. Dan Pop

    Dan Pop Guest

    In <> (Mariano) writes:

    >I hope that you could help me, I want to do a function that get a
    >string parameter and this one contains a function that I want to
    >execute.
    >
    >Ex.
    >//---------------------------------------
    >// Test.c
    >//---------------------------------------
    >#include <stdio.h>
    >void func1(char *);
    >void func2(int);
    >int main(int argc, char *argv[]){
    > MyFunc(argv[1]);
    >}
    >
    >void MyFunc(char *s){
    > ...
    > How evaluate this string?
    > ...
    >}
    >void func1(char *s){ printf("%s\n",s); }
    >void func2(int a){ printf("%d\n",a); }
    >//---------------------------------------
    >
    ># ./Test "func1('Hi')"


    What you really want here is:

    ./Test 'func1("Hi")'

    So that argv[1] looks syntactically correct to your parser.

    >Hi
    >
    ># ./Test "func2(123)"
    >123


    The first thing is to redesign the program so that the first argument
    is the function name and the following ones are the function arguments.

    So, the sample invocations of your programs become:

    ./Test func1 Hi
    ./Test func2 123

    The next thing is to redesign your functions, so that they extract their
    arguments from from the command line arguments:

    void func1(int argc, char **argv) { ... }
    void func2(int argc, char **argv) { ... }

    Now we can simply drop MyFunc() and write main() like this:

    int main(int argc, char **argv)
    {
    if (argc < 2 ) /* wrong invocation of the program */ ;
    if (strcmp(argv[1], "func1") == 0) func1(argc, argv);
    else if (strcmp(argv[1], "func2") == 0) func2(argc, argv);
    else /* invalid function name */ ;
    return 0;
    }

    Of course, in a real application, you may want to build a symbol table,
    instead of explicitly comparing against each possible function name.

    This can be accomplished with an array of structures of the following
    format:

    struct st_entry {
    char name[32];
    void (*address)();
    } symtab[] = {
    {"func1", func1},
    {"func2", func2}
    };

    Now, you can put the following loop in main():

    for (i = 0; i < sizeof symtab / sizeof symtab[0]; i++) {
    if (strcmp(argv[1], symtab.name) == 0) {
    symtab.address(argc, argv);
    break;
    }
    }

    If we put all the bits together, we get the following minimal program
    that matches our revised specification. For simplicity reasons, error
    checking is performed, but detected errors are not reported (other than
    via the exit status).

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>

    void func1(int argc, char **argv)
    {
    if (argc < 3) exit(EXIT_FAILURE);
    puts(argv[2]);
    }

    void func2(int argc, char **argv)
    {
    if (argc < 3) exit(EXIT_FAILURE);
    printf("%d\n", atoi(argv[2]));
    }

    struct st_entry {
    char name[32];
    void (*address)();
    } symtab[] = {
    {"func1", func1},
    {"func2", func2}
    };

    int main(int argc, char **argv)
    {
    int i;

    if (argc < 2) return EXIT_FAILURE;
    for (i = 0; i < sizeof symtab / sizeof symtab[0]; i++) {
    if (strcmp(argv[1], symtab.name) == 0) {
    symtab.address(argc, argv);
    break;
    }
    }
    return 0;
    }

    Now, you have enough information to implement your original specification,
    but it would take a lot more effort for no redeeming advantages. This is
    also an excellent example of minimal design changes having a major impact
    on the coding effort.

    Dan
    --
    Dan Pop
    DESY Zeuthen, RZ group
    Email:
    Dan Pop, Jun 24, 2003
    #1
    1. Advertising

  2. Dan Pop

    Tom St Denis Guest

    Thomas Matthews wrote:
    > Dan Pop wrote:
    >
    >> In <>
    >> (Mariano) writes:

    >
    > [snip]
    >
    >> Of course, in a real application, you may want to build a symbol table,
    >> instead of explicitly comparing against each possible function name.
    >>
    >> This can be accomplished with an array of structures of the following
    >> format:
    >>
    >> struct st_entry {
    >> char name[32];
    >> void (*address)();
    >> } symtab[] = {
    >> {"func1", func1},
    >> {"func2", func2}
    >> };
    >>
    >> Now, you can put the following loop in main():
    >>
    >> for (i = 0; i < sizeof symtab / sizeof symtab[0]; i++) {
    >> if (strcmp(argv[1], symtab.name) == 0) {
    >> symtab.address(argc, argv);
    >> break;
    >> }
    >> }

    >
    > [snip]
    >
    >>
    >> Dan

    >
    >
    > Since the 'address' field of the structure is a pointer
    > to a function, doesn't it need to be dereferenced as in:
    > (*(symtab.address)) (argc, argv);
    >
    > If not, please explain or elaborate.


    Nope. All function names are pointers by default in C. e.g.

    &printf == printf

    is true [just tried it to make sure... hehehehe]

    So you don't have to dereference it [unless you had an array of
    functions in which case dereferencing the name would be the same as the
    function address in the zero'th location]

    Tom
    Tom St Denis, Jun 24, 2003
    #2
    1. Advertising

  3. Dan Pop

    Zoran Cutura Guest

    Thomas Matthews <> wrote:
    > Dan Pop wrote:
    >> In <> (Mariano) writes:

    > [snip]
    >
    >> Of course, in a real application, you may want to build a symbol table,
    >> instead of explicitly comparing against each possible function name.
    >>
    >> This can be accomplished with an array of structures of the following
    >> format:
    >>
    >> struct st_entry {
    >> char name[32];
    >> void (*address)();
    >> } symtab[] = {
    >> {"func1", func1},
    >> {"func2", func2}
    >> };
    >>
    >> Now, you can put the following loop in main():
    >>
    >> for (i = 0; i < sizeof symtab / sizeof symtab[0]; i++) {
    >> if (strcmp(argv[1], symtab.name) == 0) {
    >> symtab.address(argc, argv);
    >> break;
    >> }
    >> }

    > [snip]
    >
    >>
    >> Dan

    >
    > Since the 'address' field of the structure is a pointer
    > to a function, doesn't it need to be dereferenced as in:
    > (*(symtab.address)) (argc, argv);
    >
    > If not, please explain or elaborate.
    >
    > I use tables of function pointer a lot. Your syntax
    > is a lot simpler than what I've used (above).


    The funny thing about functions is that the expression in front of a
    ()-operator has to be a pointer to a function in any case which in the
    very most cases (every time we use a simple identifier designating a
    function) is produced by converting a function designator into a pointer
    to that function.

    ISO/IEC 9899:1999 6.3.2.1
    A function designator is an expression that has function type. Except
    when it is the operand of the sizeof operator or the unary &
    operator, a function designator with type function returning type is
    converted to an expression that has type pointer to function returning
    type.

    Because a pointer to a function already has the appropriate type one
    doesn't need to dereference it to than get a function designator that
    again is converted to a pointer to function.


    --
    Z ()
    "LISP is worth learning for the profound enlightenment experience
    you will have when you finally get it; that experience will make you
    a better programmer for the rest of your days." -- Eric S. Raymond
    Zoran Cutura, Jun 24, 2003
    #3
  4. Tom St Denis wrote:
    > Thomas Matthews wrote:
    >
    >> Dan Pop wrote:
    >>
    >>> In <>
    >>> (Mariano) writes:

    >>
    >>
    >> [snip]
    >>
    >>> Of course, in a real application, you may want to build a symbol table,
    >>> instead of explicitly comparing against each possible function name.
    >>>
    >>> This can be accomplished with an array of structures of the following
    >>> format:
    >>>
    >>> struct st_entry {
    >>> char name[32];
    >>> void (*address)();
    >>> } symtab[] = {
    >>> {"func1", func1},
    >>> {"func2", func2}
    >>> };
    >>>
    >>> Now, you can put the following loop in main():
    >>>
    >>> for (i = 0; i < sizeof symtab / sizeof symtab[0]; i++) {
    >>> if (strcmp(argv[1], symtab.name) == 0) {
    >>> symtab.address(argc, argv);
    >>> break;
    >>> }
    >>> }

    >>
    >>
    >> [snip]
    >>
    >>>
    >>> Dan

    >>
    >>
    >>
    >> Since the 'address' field of the structure is a pointer
    >> to a function, doesn't it need to be dereferenced as in:
    >> (*(symtab.address)) (argc, argv);
    >>
    >> If not, please explain or elaborate.

    >
    >
    > Nope. All function names are pointers by default in C. e.g.
    >
    > &printf == printf
    >
    > is true [just tried it to make sure... hehehehe]
    >
    > So you don't have to dereference it [unless you had an array of
    > functions in which case dereferencing the name would be the same as the
    > function address in the zero'th location]
    >
    > Tom
    >


    I'm still confused. Does a function pointer need to be dereferenced?
    Given:
    void (*p_function)(); /* pointer to function returning void */

    /* ... code to initialize p_function */
    /* 1 */ p_function(); /* Will this execute the function pointed */
    /* to by the variable 'p_function'? */
    /* 2 */ (*p_function)(); /* This is what I've always used. */

    My understanding is that Dan's statement using the field of the
    structure evaluates to line #1 above. Most C books I read use
    line #2.

    I give in. According to "C, A Reference Manual", by Harbison
    and Steele, section 5.8,:
    In ANSI C and some other implementations, an expression
    of type "pointer to function" can be used in a function call
    without an explicit dereferencing; in that case, the call
    (*fp)(j,k) above can be written as fp(j,k).

    --
    Thomas Matthews

    C Faq: http://www.eskimo.com/~scs/c-faq/top.html
    alt.comp.lang.learn.c-c++ faq:
    http://www.raos.demon.uk/acllc-c /faq.html
    Thomas Matthews, Jun 24, 2003
    #4
  5. On Tue, 24 Jun 2003, Thomas Matthews wrote:
    >
    > Tom St Denis wrote:
    > > Thomas Matthews wrote:
    > >> Dan Pop wrote:
    > >>>
    > >>> symtab.address(argc, argv);
    > >>
    > >> Since the 'address' field of the structure is a pointer
    > >> to a function, doesn't it need to be dereferenced as in:
    > >> (*(symtab.address)) (argc, argv);

    > >
    > > Nope. All function names are pointers by default in C.

    >
    > I'm still confused. Does a function pointer need to be dereferenced?
    >
    > void (*p_function)(); /* pointer to function returning void */
    >
    > /* 1 */ p_function(); /* Will this execute the function pointed */
    > /* to by the variable 'p_function'? */
    > /* 2 */ (*p_function)(); /* This is what I've always used. */
    >
    > My understanding is that Dan's statement using the field of the
    > structure evaluates to line #1 above. Most C books I read use
    > line #2.


    Because it's clearer, and slightly more traditional (IMHE).

    > I give in. According to "C, A Reference Manual", by Harbison
    > and Steele, section 5.8,:
    > In ANSI C and some other implementations, an expression

    ^^^^^^
    Pre-ANSI C implementations may not have had the same rules about what
    decays to what, or what goes before () in a function call. I think
    K&R1 used a few function pointers here and there, always with (*fn)()
    syntax, but I could be mistaken, and it might've changed in the second
    edition anyway (though I would be surprised).

    Note that declaration reflects use in the "traditional" usage:

    {
    int (*fn)() = getchar;
    int x = (*fn)();
    }

    but not in the "ANSI" usage:

    {
    int (*fn)() = getchar;
    int x = fn(); /* !! */
    }

    Anyway, I prefer to use (*fn)() with function pointers, as it makes things
    abundantly clear that 'fn' is a pointer, NOT a function designator, and
    that the value of 'fn' might (in fact, *should*) change in the course of
    execution.

    Unfortunately, AIUI modern C compilers have to resort to ad-hoc hacks in
    order to support the (*fn)() usage, since it doesn't follow any rhyme or
    reason with respect to the rest of the language as far as functions are
    concerned. IMO that's not a valid reason to avoid (*fn)(), though.

    Anyway, I'd have re-written your example to be clearer in a different
    way.

    original: (*(symtab.address)) (argc, argv);

    mine:
    (*symtab.address)(argc, argv);
    or:
    void (*fn)(int, char**) = symtab.address;
    (*fn)(argc, argv);

    My $.02,
    -Arthur
    Arthur J. O'Dwyer, Jun 24, 2003
    #5
  6. Dan Pop

    Dan Pop Guest

    In <> Thomas Matthews <> writes:

    >Dan Pop wrote:
    >> In <> (Mariano) writes:

    >[snip]
    >
    >> Of course, in a real application, you may want to build a symbol table,
    >> instead of explicitly comparing against each possible function name.
    >>
    >> This can be accomplished with an array of structures of the following
    >> format:
    >>
    >> struct st_entry {
    >> char name[32];
    >> void (*address)();
    >> } symtab[] = {
    >> {"func1", func1},
    >> {"func2", func2}
    >> };
    >>
    >> Now, you can put the following loop in main():
    >>
    >> for (i = 0; i < sizeof symtab / sizeof symtab[0]; i++) {
    >> if (strcmp(argv[1], symtab.name) == 0) {
    >> symtab.address(argc, argv);
    >> break;
    >> }
    >> }

    >
    >Since the 'address' field of the structure is a pointer
    >to a function, doesn't it need to be dereferenced as in:
    > (*(symtab.address)) (argc, argv);
    >
    >If not, please explain or elaborate.


    Standard C allows, but does not require your syntax. Because a function
    name decays into a function pointer, the () operator takes a function
    pointer as argument:

    6.5.2.2 Function calls

    Constraints

    1 The expression that denotes the called function 77) shall have
    type pointer to function returning void or returning an object
    type other than an array type.

    ____________________

    77) Most often, this is the result of converting an identifier
    that is a function designator.

    Back in the days of pre-ANSI C, your syntax was mandatory.

    >I use tables of function pointer a lot. Your syntax
    >is a lot simpler than what I've used (above).


    Indeed, but I prefer not to use it on plain function pointers:

    void (*func)(void);
    ...
    func();

    because it could be easily confused with a normal function call and
    someone might start looking for the definition of the func function.
    In such cases, I prefer to use the old syntax:

    (*func)();

    to make it clear that I'm dereferencing a function pointer. When the
    function pointer is part of an aggregate type, there is no such risk,
    so I apply the () operator directly to the expression yielding the pointer
    value, as in the code snippet from my previous post, quoted above.

    Dan
    --
    Dan Pop
    DESY Zeuthen, RZ group
    Email:
    Dan Pop, Jun 24, 2003
    #6
  7. Tom St Denis wrote:
    >
    > Thomas Matthews wrote:


    <snip>

    > >>>
    > >>> Since the 'address' field of the structure is a pointer
    > >>> to a function, doesn't it need to be dereferenced as in:
    > >>> (*(symtab.address)) (argc, argv);
    > >>>
    > >>> If not, please explain or elaborate.
    > >>
    > >>
    > >>
    > >> Nope. All function names are pointers by default in C. e.g.


    Not true. The Standard says:

    "A function designator is an expression that has function type. Except
    when it is the operand of the sizeof operator54) or the unary &
    operator, a function designator with type ‘‘function returning type’’ is
    converted to an expression that has type ‘‘pointer to function returning
    type’’."

    In other words, a function designator is /not/ a function pointer.
    Rather, it is converted into a function pointer expression in most
    circumstances. This is a little like the array-decays-to-pointer rule.

    > >> &printf == printf
    > >>
    > >> is true [just tried it to make sure... hehehehe]


    This is indeed true, because the & is ignored by the compiler.


    <snip>
    > >
    > > I'm still confused. Does a function pointer need to be dereferenced?
    > > Given:
    > > void (*p_function)(); /* pointer to function returning void */

    >
    > No you don't. Recall the "function names are pointers by default."


    Wrong.

    >
    > So you don't call
    >
    > (*printf)("%s", "hello");
    >
    > Do you?


    Irrelevant.

    <snip>

    --
    Richard Heathfield :
    "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
    C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
    K&R answers, C books, etc: http://users.powernet.co.uk/eton
    Richard Heathfield, Jun 24, 2003
    #7
    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. Jim Hammond
    Replies:
    2
    Views:
    4,499
    bruce barker
    Nov 14, 2003
  2. Larry__Weiss

    Re: To execute a string as function

    Larry__Weiss, Jun 24, 2003, in forum: C Programming
    Replies:
    0
    Views:
    729
    Larry__Weiss
    Jun 24, 2003
  3. TheDustbustr
    Replies:
    1
    Views:
    425
    Sami Hangaslammi
    Jul 25, 2003
  4. Rajarshi Guha

    how can I execute a function string

    Rajarshi Guha, Jan 13, 2004, in forum: Python
    Replies:
    3
    Views:
    292
    Rajarshi Guha
    Jan 14, 2004
  5. Savas Ates
    Replies:
    1
    Views:
    266
    Patrice
    Aug 17, 2004
Loading...

Share This Page