parameter and functionpointer

Discussion in 'C Programming' started by humblemark, Nov 22, 2007.

  1. humblemark

    humblemark Guest

    Hello,

    I try to give a parameter in the function tt; but omething went
    wrong?? Any idea what i can do??



    int ret_integer()
    {
    return 76;
    }


    int (*tt(int dummy))()
    {

    return ((int(*)()) ret_integer());
    }


    int main()
    { int(*pq)();
    pq = tt(23);
    pq(); // bang bang
    return 0;
    }

    Thanks a lot C folks
     
    humblemark, Nov 22, 2007
    #1
    1. Advertising

  2. humblemark wrote:
    > Hello,
    >
    > I try to give a parameter in the function tt; but omething went
    > wrong?? Any idea what i can do??



    As is often the case, when your code starts filling up with casts, it is
    probably wrong. The parameter is not the problem: it is the () on the
    return value from tt. And the silly cast can't help; it can only mask
    errors. Compare the following:

    #include <stdio.h>

    int ret_integer()
    {
    return 76;
    }

    int (*tt(int dummy)) ()
    {
    (void) dummy;
    return ret_integer;
    }

    int main()
    {
    int (*pq) ();
    pq = tt(23);
    printf("pq() = %d\n", pq());
    return 0;
    }


    [OP's code]

    > int ret_integer()
    > {
    > return 76;
    > }
    >
    >
    > int (*tt(int dummy))()
    > {
    >
    > return ((int(*)()) ret_integer());
    > }
    >
    >
    > int main()
    > { int(*pq)();
    > pq = tt(23);
    > pq(); // bang bang
    > return 0;
    > }
    >
    > Thanks a lot C folks
     
    Martin Ambuhl, Nov 22, 2007
    #2
    1. Advertising

  3. humblemark

    Guest

    On 22 Nov, 21:13, humblemark <> wrote:
    > Hello,
    >
    > I try to give a parameter in the function tt; but omething went
    > wrong?? Any idea what i can do??
    >
    > int ret_integer()
    > {
    > return 76;
    >
    > }
    >
    > int (*tt(int dummy))()
    > {
    >
    > return ((int(*)()) ret_integer());


    This line is your problem. ret_integer is a function that returns an
    integer. So ret_integer() runs that function, and produces an integer
    result (of 76). tt returns that value of 76, horribly cast into a
    function pointer. This is, I presume, not what you want. The value you
    want out is ret_integer itself, not the result of running it. So miss
    off the () after ret_integer, and you get:

    return ((int(*)()) ret_integer);

    which seems to work fine for me. So well, in fact, that you can miss
    out the cast altogether and simply say:

    return ret_integer;

    > }
    >
    > int main()
    > { int(*pq)();
    > pq = tt(23);
    > pq(); // bang bang
    > return 0;
    >
    > }


    Hope that helps.
    Paul.
     
    , Nov 22, 2007
    #3
  4. humblemark wrote:
    > I try to give a parameter in the function tt; but omething went
    > wrong?? Any idea what i can do??


    The first thing you should do is read
    <http://www.catb.org/~esr/faqs/smart-questions.html>.

    Telling us that "something went wrong" is not particularly useful.
    *What* went wrong?

    As it happens, you've given us enough information to figure out the problem.

    > int ret_integer()
    > {
    > return 76;
    > }


    Ok, ``ret_integer'' is a function returning an int. It has no
    parameters, but it's better to make that explicit; I'd change the
    declaration from ``int reg_integer()'' to ``int reg_integer(void)''.
    (This isn't your main problem.

    > int (*tt(int dummy))()


    ``tt'' is a function that takes an int argument, and returns a pointer
    to a function that returns an int. The returned function takes no
    arguments; again, it's better to make this explicit:

    int (*tt(int dummy))(void)

    > {
    >
    > return ((int(*)()) ret_integer());


    The expression ``ret_integer()'' *calls* your function and yields the
    value that it returns (76, of type int). You then explicitly convert
    the int value 76 to a pointer-to-function type, which gives you garbage.

    What you want here is not ``ret_integer()'' (the result of calling the
    function), but ``ret_integer'' (the name of the function, which decays
    to a pointer to the function in this context).

    I'm guessing that you added the cast to silence a compile-time error.
    That should have made you suspicious. Most (but not all) casts are
    actually unnecessary. All you need here is ``return ret_integer;''.

    > }
    >
    >
    > int main()


    Ok, but ``int main(void)'' is preferred.

    > { int(*pq)();
    > pq = tt(23);
    > pq(); // bang bang


    And here you try to make a function call through the garbage pointer.
    The result is undefined behavior (most likely your program crashes).

    > return 0;
    > }


    Here's a version of your program that displays the result of the call:

    #include <stdio.h>

    int ret_integer(void)
    {
    return 76;
    }

    int (*tt(int dummy))(void)
    {
    return ret_integer;
    }

    int main()
    {
    int(*pq)(void) = tt(23);
    printf("pq() returns %d\n", pq());
    return 0;
    }

    --
    Keith Thompson (The_Other_Keith)
    Looking for software development work in the San Diego area.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Nov 22, 2007
    #4
  5. humblemark

    Flash Gordon Guest

    humblemark wrote, On 22/11/07 21:13:
    > Hello,
    >
    > I try to give a parameter in the function tt; but omething went
    > wrong?? Any idea what i can do??


    I suggest that you need to learn to use a debugger. Had you done so and
    checked the value of pq when you made the call the error would have been
    obvious.

    > int ret_integer()
    > {
    > return 76;
    > }
    >
    >
    > int (*tt(int dummy))()


    Using a typedef for the function type would make this a lot easier to read.

    > {
    >
    > return ((int(*)()) ret_integer());


    Did you add this case to get rid of a warning? If so you did exactly the
    WRONG thing. The case does not fix the code it just stops the compiler
    from telling you about your mistake.
    return ret_integer;

    > }
    >
    >
    > int main()
    > { int(*pq)();
    > pq = tt(23);
    > pq(); // bang bang
    > return 0;
    > }
    >
    > Thanks a lot C folks


    Other general points:

    When a function does not take parameters it is better to be explicit so
    that the compiler will warn you if you pass parameters in error. E.g.
    int (*tt(int dummy))(void)

    Using // style comments in posts to Usenet is generally a bad idea
    because they do not survive line wrapping.

    Please don't use tabs when posting code, sometimes they get stripped by
    a server along the way loosing the formatting and other times they are
    not rendered by the client in the same way they appear in your editor.
    For posting to Usenet always use spaces for indenting.
    --
    Flash Gordon
     
    Flash Gordon, Nov 22, 2007
    #5
  6. On Thu, 22 Nov 2007 13:13:41 -0800 (PST), humblemark
    <> wrote:

    >Hello,
    >
    >I try to give a parameter in the function tt; but omething went
    >wrong?? Any idea what i can do??
    >
    >
    >
    >int ret_integer()


    ret_integer is a function with unspecified arguments returning int

    >{
    >return 76;
    >}
    >
    >
    >int (*tt(int dummy))()


    tt is a function
    with a single (unused) parameter of type int
    returning a pointer to function
    with unspecified arguments
    returning type int

    The return type of tt matches ret_integer. So far so good.

    >{
    >
    >return ((int(*)()) ret_integer());


    ret_integer() evaluates to an int. You are attempting to cast this
    int to a function pointer. I don't think that is what you want. (What
    makes you think there is a valid function at address 76?) I think you
    want to return the address of ret_integer. You do this by using the
    function name without parentheses. This expression evaluates to the
    function address with type pointer to function which I think is what
    you do want. The statement should read
    return ret_integer;

    Since this corrected expression is of type pointer to function with
    unspecified arguments returning int, the cast serves no purpose since
    it tries to convert the expression to the same type. My crystal ball
    tells me you added the cast to silence a diagnostic when your original
    code said
    return ret_integer();
    Let this be the example that convinces you that adding a cast to
    silence a diagnostic is ALMOST ALWAYS the wrong solution. Only use a
    cast when you are absolutely certain it will do what you want.

    >}
    >
    >
    >int main()
    >{ int(*pq)();
    > pq = tt(23);
    > pq(); // bang bang


    After you make the above correction, you still have no idea if this
    statement worked. Maybe you want to print the value of this
    expression.

    > return 0;
    >}



    Remove del for email
     
    Barry Schwarz, Nov 23, 2007
    #6
  7. On Nov 23, 1:05 pm, Barry Schwarz <> wrote:
    > On Thu, 22 Nov 2007 13:13:41 -0800 (PST), humblemark
    > <> wrote:
    > >Hello,

    >
    > >I try to give a parameter in the function tt; but omething went
    > >wrong?? Any idea what i can do??

    >
    > >int ret_integer()

    >
    > ret_integer is a function with unspecified arguments returning int


    While I wouldn't say it's good practice, an empty parameter list for
    the definition of a function means there are no arguments:

    6.7.5.3 paragraph 14 (in N1256): "An empty list in a function
    declarator that is part of a definition of that function specifies
    that the function has no parameters. The empty list in a function
    declarator that is not part of a definition of that function specifies
    that no information about the number or types of the parameters is
    supplied."
     
    Justin Spahr-Summers, Nov 23, 2007
    #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. Andreas Klimas

    functionpointer prototype with void* : question

    Andreas Klimas, Sep 15, 2006, in forum: C Programming
    Replies:
    4
    Views:
    308
    Keith Thompson
    Sep 15, 2006
  2. Replies:
    4
    Views:
    524
    Matteo
    Mar 29, 2007
  3. news.aioe.org
    Replies:
    2
    Views:
    271
    diamondback
    Oct 7, 2008
  4. Anonimo
    Replies:
    0
    Views:
    295
    Anonimo
    Nov 18, 2009
  5. RHS
    Replies:
    4
    Views:
    770
    John H.
    Jan 13, 2010
Loading...

Share This Page