void* question

Discussion in 'C Programming' started by Janet, Feb 10, 2008.

  1. Janet

    Janet Guest

    What is the major reason for using void*?
    When should we use void* for both input arguments and return value?
    How can we cast the void* pointer to the type we need?
    Thanx
    Janet, Feb 10, 2008
    #1
    1. Advertising

  2. "Janet" <> wrote in message news
    > What is the major reason for using void*?
    > When should we use void* for both input arguments and return value?
    > How can we cast the void* pointer to the type we need?
    > Thanx
    >

    Take a proposed addition to the standard library.

    void memswap(void *ptr1, void *ptr2, size_t len)

    it simply exchanges two areas of memory.
    So to swap two integers we would write

    int i, j;
    memswap(&i, &j, sizeof(int));

    to exchange two doubles

    double x, y;
    memswap(&x, &y, sizeof(double));

    and so on.

    The void * parameters mean we don't need ugly casts. Internally, however,
    memswap will handle the pointers as unsigned char *s. It doesn't need to
    understand what it swaps, it just sees two areas of memory.

    --
    Free games and programming goodies.
    http://www.personal.leeds.ac.uk/~bgy1mm
    Malcolm McLean, Feb 10, 2008
    #2
    1. Advertising

  3. Janet

    Ben Pfaff Guest

    Janet <> writes:

    > What is the major reason for using void*?


    A pointer to void is often used when the type of data that a
    pointer points to is unknown at compile time.

    > When should we use void* for both input arguments and return value?


    When the above is true about input arguments and return values.

    > How can we cast the void* pointer to the type we need?


    There is rarely a need to cast a pointer to void, because most
    conversions from a pointer to void to a pointer to another object
    type can take place implicitly, but the syntax is no different
    from that for any other cast.
    --
    "In My Egotistical Opinion, most people's C programs should be indented six
    feet downward and covered with dirt." -- Blair P. Houghton
    Ben Pfaff, Feb 10, 2008
    #3
  4. Janet

    Eric Sosman Guest

    Janet wrote:
    > What is the major reason for using void*?


    To deal with a pointer when the type of the thing
    it points to is unknown or unimportant. For example,
    the malloc() function allocates memory but does not
    know or need to know what kind of data you intend to
    store in it.

    > When should we use void* for both input arguments and return value?


    As above.

    > How can we cast the void* pointer to the type we need?


    With a cast operator, like `(int*)ptr' or `(char*)ptr'.
    Since the void* pointer carries no information about the
    kind of data it points to, you need some other way to
    figure out which cast operator is appropriate.

    --
    Eric Sosman
    lid
    Eric Sosman, Feb 10, 2008
    #4
  5. Janet

    Flash Gordon Guest

    Eric Sosman wrote, On 10/02/08 21:49:
    > Janet wrote:


    <snip>

    >> How can we cast the void* pointer to the type we need?

    >
    > With a cast operator, like `(int*)ptr' or `(char*)ptr'.
    > Since the void* pointer carries no information about the
    > kind of data it points to, you need some other way to
    > figure out which cast operator is appropriate.


    More often than not you should not cast the pointer at all. This is
    because it is implicitly converted when assigned to a variable of
    another type. So Janet should *not* cast the result of malloc.
    --
    Flash Gordon
    Flash Gordon, Feb 10, 2008
    #5
  6. Janet:

    > What is the major reason for using void*?
    > When should we use void* for both input arguments and return value?
    > How can we cast the void* pointer to the type we need?
    > Thanx



    A void* is really just a char* that has few more "features" (...or even
    "lack of features").

    The differences between char* and void* are:
    1) void* has implicit conversion to and from every other pointer type.
    2) You can do pointer arithmetic on a char*, but NOT on a void*.
    3) You can dereference a char*, but not a void*.

    Basically the idea is that you use a void* when you aren't certain what
    you're going to be pointing to. You might be pointing to an int one minute,
    then a double the next.

    At the end of the day tho, both void* and char* really just store the
    address of a byte.

    --
    Tomás Ó hÉilidhe
    Tomás Ó hÉilidhe, Feb 11, 2008
    #6
  7. Janet

    Jack Klein Guest

    On Sun, 10 Feb 2008 22:41:58 +0000, Flash Gordon
    <> wrote in comp.lang.c:

    > Eric Sosman wrote, On 10/02/08 21:49:
    > > Janet wrote:

    >
    > <snip>
    >
    > >> How can we cast the void* pointer to the type we need?

    > >
    > > With a cast operator, like `(int*)ptr' or `(char*)ptr'.
    > > Since the void* pointer carries no information about the
    > > kind of data it points to, you need some other way to
    > > figure out which cast operator is appropriate.

    >
    > More often than not you should not cast the pointer at all. This is
    > because it is implicitly converted when assigned to a variable of
    > another type. So Janet should *not* cast the result of malloc.


    More correctly, pointer to void is implicitly converted by assignment
    to a pointer to any object type. It is not implicitly converted, nor
    is there a defined cast, from pointer to void to any arithmetic type,
    aggregate type, or pointer to function.

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://c-faq.com/
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
    Jack Klein, Feb 11, 2008
    #7
  8. Janet

    Janet Guest

    On 11 Feb 2008 at 4:03, Jack Klein wrote:
    > On Sun, 10 Feb 2008 22:41:58 +0000, Flash Gordon
    ><> wrote in comp.lang.c:
    >
    >> Eric Sosman wrote, On 10/02/08 21:49:
    >> > Janet wrote:

    >>
    >> <snip>
    >>
    >> >> How can we cast the void* pointer to the type we need?
    >> >
    >> > With a cast operator, like `(int*)ptr' or `(char*)ptr'.
    >> > Since the void* pointer carries no information about the
    >> > kind of data it points to, you need some other way to
    >> > figure out which cast operator is appropriate.

    >>
    >> More often than not you should not cast the pointer at all. This is
    >> because it is implicitly converted when assigned to a variable of
    >> another type. So Janet should *not* cast the result of malloc.

    >
    > More correctly, pointer to void is implicitly converted by assignment
    > to a pointer to any object type. It is not implicitly converted, nor
    > is there a defined cast, from pointer to void to any arithmetic type,
    > aggregate type, or pointer to function.


    Could you say what you mean by "no defined cast to pointer to function"?

    Maybe I should elaborate on the question. Basically I'm coming from JAVA
    and trying to implement polymorphism via an array of function pointers.

    The functions all take the same arguments, but they have different
    return values, e.g.
    int f1(int x, int y);
    double f2(int x, int y);
    etc.

    As I'm never actually going to need the return value I was hoping to use
    a void* instead of actual function pointers to let me ignore the
    difference between the return types of the functions. Is that going to
    work?
    Janet, Feb 11, 2008
    #8
  9. "Janet" <> wrote in message
    > On 11 Feb 2008 at 4:03, Jack Klein wrote:
    >> On Sun, 10 Feb 2008 22:41:58 +0000, Flash Gordon
    >><> wrote in comp.lang.c:
    >>
    >>> Eric Sosman wrote, On 10/02/08 21:49:

    > The functions all take the same arguments, but they have different
    > return values, e.g.
    > int f1(int x, int y);
    > double f2(int x, int y);
    > etc.
    >
    > As I'm never actually going to need the return value I was hoping to use
    > a void* instead of actual function pointers to let me ignore the
    > difference between the return types of the functions. Is that going to
    > work?
    >

    You need wrapper functions

    void F1(int x, int y)
    {
    gf(x, y);
    }

    void F2(int x, int y)
    {
    f2(x, y);
    }

    Now you can have a list of

    typedef void (*fptr)(int x, int y);

    fptrs (function pointers) to select the appropriate function.

    --
    Free games and programming goodies.
    http://www.personal.leeds.ac.uk/~bgy1mm
    Malcolm McLean, Feb 11, 2008
    #9
  10. Janet <> writes:

    > On 11 Feb 2008 at 4:03, Jack Klein wrote:
    >> On Sun, 10 Feb 2008 22:41:58 +0000, Flash Gordon
    >><> wrote in comp.lang.c:
    >>
    >>> Eric Sosman wrote, On 10/02/08 21:49:
    >>> > Janet wrote:
    >>>
    >>> <snip>
    >>>
    >>> >> How can we cast the void* pointer to the type we need?
    >>> >
    >>> > With a cast operator, like `(int*)ptr' or `(char*)ptr'.
    >>> > Since the void* pointer carries no information about the
    >>> > kind of data it points to, you need some other way to
    >>> > figure out which cast operator is appropriate.
    >>>
    >>> More often than not you should not cast the pointer at all. This is
    >>> because it is implicitly converted when assigned to a variable of
    >>> another type. So Janet should *not* cast the result of malloc.

    >>
    >> More correctly, pointer to void is implicitly converted by assignment
    >> to a pointer to any object type. It is not implicitly converted, nor
    >> is there a defined cast, from pointer to void to any arithmetic type,
    >> aggregate type, or pointer to function.

    >
    > Could you say what you mean by "no defined cast to pointer to
    > function"?


    He means that converting between what is often called a "data pointer"
    (a pointer to any arithmetic or aggregate type) and a function pointer
    is not permitted by the standard. Such a conversion is often provided
    as an extension, but it is not wise to rely on it.

    > Maybe I should elaborate on the question. Basically I'm coming from JAVA
    > and trying to implement polymorphism via an array of function pointers.
    >
    > The functions all take the same arguments, but they have different
    > return values, e.g.
    > int f1(int x, int y);
    > double f2(int x, int y);
    > etc.
    >
    > As I'm never actually going to need the return value I was hoping to use
    > a void* instead of actual function pointers to let me ignore the
    > difference between the return types of the functions. Is that going to
    > work?


    No, not a void * because of the above.

    You may, however, convert between and two function pointer types but
    at the point of making the call, the type of the pointer used must
    match that of the function being called.

    You can legally do this:

    typedef void generic_function(int, int);
    generic_function *fp1 = (generic_function *)f1;

    provided that when you call the pointer to function you convert the
    pointer:

    ((int (*)(int, int))fp1)(4, 2);

    This is, of course, rather ugly (some typedefs help) but, worse,
    you've got to know the type at the point of call and that can defeat
    the purpose.

    So, to avoid this, you have to have the functions returning the same
    type. You can do this by wrapping them as Malcolm McLean has
    suggested. An alternative is to edit them so they all return a union
    type which includes all the possible old return types. The down side
    of this method is that you may have existing calls like:

    int x = f1(2, 3);

    that need to be changed to:

    int x = f1(2, 3).int_value;

    but you will not have a whole bunch of extra wrappers. Of course, if
    you *really* don't need the return value, just loose it and make all the
    function return void.

    The union return is a royal pain in "old" C90. In C99 one has compound
    literals and one can write:

    typedef union value_t {
    int int_value;
    double double_value;
    } value_t;

    value_t f1(int x, int y) { return (value_t){ .int_value = x + y }; }

    One of the best parts of C99 IMHO.

    --
    Ben.
    Ben Bacarisse, Feb 11, 2008
    #10
  11. Janet:

    > Maybe I should elaborate on the question. Basically I'm coming from
    > JAVA and trying to implement polymorphism via an array of function
    > pointers.



    Rather than an array of function pointers, we simply have a struct
    containing different kinds of function pointer, reason being that we
    have the freedom to specify different return values and arguments for
    each of the functions.


    > The functions all take the same arguments, but they have different
    > return values, e.g.
    > int f1(int x, int y);
    > double f2(int x, int y);



    Yes, see, here is your problem. You should use a struct instead.

    Imagine you had the following in Java:

    (I don't actually know Java so I'm going to write C++ code, but
    hopefully you'll get the idea)

    class BaseClass {
    public:

    virtual void Speak(void) { WriteToScreen("I like ice-cream"); }
    virtual double GetValue(void) { return 7.2; }
    };

    class Derived1 : BaseClass {
    public:

    virtual void Speak(void) { WriteToScreen("I like custard"); }
    virtual double GetValue(void) { return 2.44; }
    };

    class Derived2 : BaseClass {
    public:

    virtual void Speak(void) { WriteToScreen("I like jelly"); }
    virtual double GetValue(void) { return 63.8; }
    };


    If we wanted to implement this in C, then we'd have:


    struct VTable {
    void (*const Speak)(void);
    double (*const GetValue)(void);
    };

    struct BaseClass {
    VTable const *const pvt;
    };

    struct Derived1 {
    VTable const *const pvt;
    };

    struct Derived2 {
    VTable const *const pvt;
    };

    Then, if you wanted to invoke Speak on an object, you'd do:

    void ExploitPolymorphism(Derived2 *const p)
    {
    p->pvt->Speak();

    p->pvt->GetValue();
    }


    (And yes, the methods I've written should of course have been declared
    const, but I left it out so as not to clutter things).

    --
    Tomás Ó hÉilidhe
    Tomás Ó hÉilidhe, Feb 11, 2008
    #11
  12. Groovy hepcat Tomás Ó hÉilidhe was jivin' in comp.lang.c on Mon, 11 Feb
    2008 11:17 am. It's a cool scene! Dig it.

    > Janet:
    >
    >> What is the major reason for using void*?
    >> When should we use void* for both input arguments and return value?
    >> How can we cast the void* pointer to the type we need?
    >> Thanx

    >
    > A void* is really just a char* that has few more "features" (...or
    > even "lack of features").


    Wrong, I'm afraid. A void * is not a char * at all. Although they do
    have the same size and representation, this does not make them the same
    thing, by any means.

    > The differences between char* and void* are:
    > 1) void* has implicit conversion to and from every other pointer type.


    Wrong again. void * has implicit conversion to and from every pointer
    to object and incomplete type, but not pointer to function type.

    --
    Dig the sig!

    ----------- Peter 'Shaggy' Haywood ------------
    Ain't I'm a dawg!!
    Peter 'Shaggy' Haywood, Feb 12, 2008
    #12
  13. Peter 'Shaggy' Haywood:

    > Although they do have the same size and representation, this does not
    > make them the same thing, by any means.



    Same size and representation is good enough for me -- they're the same
    thing just with a different interface to the programmer.


    > void * has implicit conversion to and from every pointer
    > to object and incomplete type, but not pointer to function type.



    Nice catch, thanks for the correction.

    --
    Tomás Ó hÉilidhe
    Tomás Ó hÉilidhe, Feb 13, 2008
    #13
  14. Janet

    Ian Collins Guest

    Tomás Ó hÉilidhe wrote:
    > Peter 'Shaggy' Haywood:
    >
    >> Although they do have the same size and representation, this does not
    >> make them the same thing, by any means.

    >
    >
    > Same size and representation is good enough for me -- they're the same
    > thing just with a different interface to the programmer.
    >

    Try dereferencing them and see what you get...

    --
    Ian Collins.
    Ian Collins, Feb 13, 2008
    #14
  15. Ian Collins:

    >> Same size and representation is good enough for me -- they're the same
    >> thing just with a different interface to the programmer.
    >>

    > Try dereferencing them and see what you get...



    I covered this in my list of differences between char* and void* upthread.

    --
    Tomás Ó hÉilidhe
    Tomás Ó hÉilidhe, Feb 13, 2008
    #15
    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. Ollej Reemt
    Replies:
    7
    Views:
    526
    Jack Klein
    Apr 22, 2005
  2. Stig Brautaset

    `void **' revisited: void *pop(void **root)

    Stig Brautaset, Oct 25, 2003, in forum: C Programming
    Replies:
    15
    Views:
    788
    The Real OS/2 Guy
    Oct 28, 2003
  3. Replies:
    5
    Views:
    831
    S.Tobias
    Jul 22, 2005
  4. Giannis Papadopoulos

    void vs void* (philosophical question)

    Giannis Papadopoulos, Jun 30, 2006, in forum: C Programming
    Replies:
    18
    Views:
    513
    Dave Thompson
    Jul 10, 2006
  5. Replies:
    1
    Views:
    406
    Victor Bazarov
    May 23, 2007
Loading...

Share This Page