typedef function pointer

Discussion in 'C Programming' started by Cancerbero, Sep 12, 2004.

  1. Cancerbero

    Cancerbero Guest

    Hi (first, excuse me for my bad english)

    As I know, the semantics for typedef is:

    typedef A B;

    I think this makes B a synonym of A, where A is an existing data type. Is
    that right?

    Based on the previous definition of typedef, I can't understand the next:

    typedef int (*TypeFunc) (int, int);

    I think it's declaring a new type called TypeFunc. The objects of that
    type are functions returning int and accepting two integer parameters.
    But I can't understand the semantic of the last expresion. Based on the
    first definition, the last should be:

    typedef int (*) (int, int) TypeFunc;
    /* first the existing datatype (pointer to function) and then the new
    identifier datatype. */

    Well, as you can see, I really can't understand the logic of the
    semantics of typedef....

    Thanks

    --
    Sebastián Gurin (Cancerbero)
    cancerbero_sgx AT users.sourceforge.net
     
    Cancerbero, Sep 12, 2004
    #1
    1. Advertising

  2. Cancerbero

    -berlin.de Guest

    Cancerbero <> wrote:
    > As I know, the semantics for typedef is:


    > typedef A B;


    > I think this makes B a synonym of A, where A is an existing data type. Is
    > that right?


    Only in the most simple cases, so not really;-)

    > Based on the previous definition of typedef, I can't understand the next:


    > typedef int (*TypeFunc) (int, int);


    > I think it's declaring a new type called TypeFunc. The objects of that
    > type are functions returning int and accepting two integer parameters.


    That's correct if you replace 'functions' by 'pointers to functions'.
    And it defines just a new identifier for a type, not a new type (because
    'pointer to function returning int and taking two int arguments' isn't
    a new type, all you do is creating a new name for it).

    > But I can't understand the semantic of the last expresion. Based on the
    > first definition, the last should be:


    > typedef int (*) (int, int) TypeFunc;
    > /* first the existing datatype (pointer to function) and then the new
    > identifier datatype. */


    But your first definition was too restrictive. It is as if you were
    saying that a definition of a variable 'v' of type A always has the
    form

    A v;

    But while that holds in some cases, it doesn't cover cases like a
    definition of a function pointer, which you have to define like this

    int ( * func_ptr ) ( int, int );

    making 'func_ptr' a pointer to a function returning int and taking
    two int arguments.

    Now, if you compare that to the typedef you are worried about

    typedef int ( * TypeFunc ) ( int, int );

    you immediately see that a better description of the syntax of typedef
    is that the new name you want to typedef goes in the place where in a
    variable definition with that type the name of the variable would appear.

    Another example would be a typedef for an array type, e.g. an array
    of 10 ints. You would define such an array 'x' as

    int x[ 10 ];

    so, consequently, the typedef for an array of 10 ints must look
    like this:

    typedef int arr_of_ten_ints[ 10 ];

    Regards, Jens
    --
    \ Jens Thoms Toerring ___ -berlin.de
    \__________________________ http://www.toerring.de
     
    -berlin.de, Sep 13, 2004
    #2
    1. Advertising

  3. Cancerbero <> writes:
    > Hi (first, excuse me for my bad english)
    >
    > As I know, the semantics for typedef is:
    >
    > typedef A B;
    >
    > I think this makes B a synonym of A, where A is an existing data type. Is
    > that right?


    That's the syntax, not the semantics. "Syntax" refers to the way a
    construct is written in C source; "semantics" refers to what it means.
    (And actually that's not the syntax of a typedef, except in the
    simplest cases.)

    As Jens points out, it's like saying that the syntax of an object
    declaration is
    A v;
    where v is the object name and A is the type. But if you wnat v
    to be an array of 20 ints, the declaration is
    int v[20];
    which doesn't fit the simple "A v;" syntax.

    But yes, "typedef A B;" makes B a synonym of A. That's the semantics.

    > Based on the previous definition of typedef, I can't understand the next:
    >
    > typedef int (*TypeFunc) (int, int);


    Syntactically, "typedef" is treated as a storage-class specifier, like
    "extern", "static", "auto", or "register". It really isn't one (it
    doesn't specify any kind of storage class), but it turned out to be
    convenient to define the syntax that way (though one could argue that
    it's not really all that convenient after all). So if you can
    understand that

    extern int (*Typefunc) (int, int);

    declares an external pointer object called "Typefunc", that points
    to a function taking to int arguments and returning it, then you can
    understand that

    typedef int (*Typefunc) (int, int);

    declares a type name called "Typefunc", that refers to a pointer to a
    function taking to int arguments and returning it.

    Now it's just a matter of understanding C's declaration syntax.
    Unfortunately, that's a non-trivial task.

    The basic principle is that the declaration of an entity mirrors the
    use of that entity. For example:
    int *a;
    declares a as a pointer to int. You can also think of it as declaring
    that "*a" is an int.

    Dropping the extern/typedef and changing the name, consider:
    int (*foo) (int, int);
    Back off a bit and look at the declaration as a whole. It says that
    (*foo) (int, int)
    will yield an int value. It looks like a function call, so the stuff
    before the arguments
    (int, int)
    has to denote a function, so
    (*foo)
    denotes a function, so
    foo
    has to be a pointer to a function. We've already seen that the
    function takes two int arguments, and that it returns int, so we can
    conclude that
    int (*foo) (int, int);
    declares foo as a pointer object, specifically as a pointer to a
    function taking two int arguments and returning int.

    Add "extern", and it declares foo as an extern object of the same type.

    Add "typedef" instead of "extern", and it declares foo as a type name
    for the same type.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Sep 13, 2004
    #3
  4. Cancerbero

    John Bode Guest

    Cancerbero <> wrote in message news:<>...
    > Hi (first, excuse me for my bad english)
    >
    > As I know, the semantics for typedef is:
    >
    > typedef A B;
    >
    > I think this makes B a synonym of A, where A is an existing data type. Is
    > that right?
    >


    Almost, but not quite. It works when talking about simple types and
    identifiers, but breaks down for cases like what you describe below.

    You need to read up on the concept of *declarators*, since they're
    unique to C (and C++, and any other language directly derived from C).
    The declarator introduces the name being declared and supplies
    additional type information. For example, given the declaration

    int *a[10];

    the storage class is 'auto' (default), the type specifier is 'int',
    the declarator is '*a[10]', and the identifier is 'a'. The type of
    'a' is "10-element array of pointer to int"; the int-ness of 'a' is
    specified through the type specifier, but the pointer-ness and
    array-ness are specified through the declarator (incidentally, this is
    why statements like "char* a, b;" don't work the way people think they
    should; the '*' is associated with the identifier 'a', *not* the type
    specifier 'char').

    This is because C was designed with a "declaration mimics use"
    paradigm. When you reference an item in an array, you use a subscript
    operator []. When you dereference a pointer, you use the dereference
    operator *. IOW, to get the int value pointed to by the 3rd array
    element, you use the expression

    *a[2];

    which evaluates to an int type. So the idea was to make the
    declaration of 'a' look the same as a reference to 'a' in the code. I
    know this seemed like a good idea at the time, but in truth it makes
    some operations harder than they need to be, and some declarations can
    get obnoxiously difficult to write (which is where typedefs come in
    handy). I've been programming in C for almost 15 years, and I didn't
    *really* understand the concept until fairly recently.

    What the typedef storage class does is make the *identifier* within
    the declarator a synonym for an existing type. Going with the example
    above, 'a' is a 10-element array of pointer to int. So the statement

    typedef int *a[10];

    creates a synonym for the existing type "10-element array of pointer
    to int" and associates it with the identifier 'a'.

    > Based on the previous definition of typedef, I can't understand the next:
    >
    > typedef int (*TypeFunc) (int, int);
    >
    > I think it's declaring a new type called TypeFunc. The objects of that
    > type are functions returning int and accepting two integer parameters.
    > But I can't understand the semantic of the last expresion. Based on the
    > first definition, the last should be:
    >
    > typedef int (*) (int, int) TypeFunc;
    > /* first the existing datatype (pointer to function) and then the new
    > identifier datatype. */
    >


    Reference what I said above. The *declarator* is (*TypeFunc) (int,
    int), which says that the *identifier* TypeFunc is a pointer to a
    function taking two int parameters. TypeFunc becomes the typedef
    name.

    > Well, as you can see, I really can't understand the logic of the
    > semantics of typedef....
    >
    > Thanks
     
    John Bode, Sep 13, 2004
    #4
  5. Cancerbero wrote:
    > Based on the previous definition of typedef, I can't understand the next:
    >
    > typedef int (*TypeFunc) (int, int);


    This is one of the essential shortcomings of C - its declaration syntax,
    especially for functions, mixes a variety of elements in a confusing
    order. The goal, to make function type declarations resemble function
    invocations, is for many people a confusion rather than an aid. You can
    do much much worse, when you start talking about functions taking or
    returning function pointers, or start worrying about where the * or &
    goes when qualifiers abound.

    In SPECS, an alternate C++ syntax designed by Damian Conway, your
    typedef would look like this:

    type TypeFunc : ^((int, int) -> int);

    The type operator ^ means "pointer to", while X -> Y means "a function
    taking X as an argument and returning Y." This is quite a bit closer to
    what you suggested, and keeps the type info separate from the new
    identifier. See Conway's paper for more:

    http://www.csse.monash.edu.au/~damian/papers/HTML/ModestProposal.html

    --
    Derrick Coetzee
    I grant this newsgroup posting into the public domain. I disclaim all
    express or implied warranty and all liability. I am not a professional.
     
    Derrick Coetzee, Sep 13, 2004
    #5
  6. Derrick Coetzee <> scribbled the following:
    > Cancerbero wrote:
    >> Based on the previous definition of typedef, I can't understand the next:
    >>
    >> typedef int (*TypeFunc) (int, int);


    > This is one of the essential shortcomings of C - its declaration syntax,
    > especially for functions, mixes a variety of elements in a confusing
    > order. The goal, to make function type declarations resemble function
    > invocations, is for many people a confusion rather than an aid. You can
    > do much much worse, when you start talking about functions taking or
    > returning function pointers, or start worrying about where the * or &
    > goes when qualifiers abound.


    > In SPECS, an alternate C++ syntax designed by Damian Conway, your
    > typedef would look like this:


    > type TypeFunc : ^((int, int) -> int);


    > The type operator ^ means "pointer to", while X -> Y means "a function
    > taking X as an argument and returning Y." This is quite a bit closer to
    > what you suggested, and keeps the type info separate from the new
    > identifier. See Conway's paper for more:


    > http://www.csse.monash.edu.au/~damian/papers/HTML/ModestProposal.html


    That looks strangely like Haskell syntax. Perhaps later we will be
    seeing typedefs like this:

    type TypeFunc: ^(((int, int) -> int) -> (int -> int));

    meaning "pointer to a function, which takes a function taking an
    (int, int) and returning int, an returns a function taking an int
    and returning int".
    This is not currently possible in either C or C++ because they can't
    manufacture new functions at run-time but it would be nice in some
    new mixed-paradigm language.

    --
    /-- Joona Palaste () ------------- Finland --------\
    \-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
    "'I' is the most beautiful word in the world."
    - John Nordberg
     
    Joona I Palaste, Sep 14, 2004
    #6
    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. glen stark
    Replies:
    2
    Views:
    709
    Ron Natalie
    Oct 10, 2003
  2. Fraser Ross
    Replies:
    4
    Views:
    1,052
    Fraser Ross
    Aug 14, 2004
  3. murgan
    Replies:
    6
    Views:
    4,869
    Thad Smith
    Dec 21, 2005
  4. robin liu
    Replies:
    3
    Views:
    824
    Robin Liu
    Apr 21, 2006
  5. oor
    Replies:
    0
    Views:
    1,356
Loading...

Share This Page