void* argument to get the result of a function

Discussion in 'C++' started by foice, Jul 27, 2010.

  1. foice

    foice Guest

    Hello to everybody. I read, and succesfully implented, some example of
    use of a void* argument to pass a generic type argument to a function.
    As far as I understand the trick is to recast the pointer to a pointer
    of the correct type and then use this pointer as usual.

    int f(void * input) {
    float * x =(float*) input;
    flaot value;
    value=*x
    cout<<value<<endl;

    return 0
    }

    Now suppose that I want to compute something can I store this
    "something" into a void* that is an argument of the function? I tried
    this, but the value of the variable is not changed, as when I make a
    cout it gives the same value of the initialization :( .

    int f(void * argument) {

    float result;
    result=0;

    argument=&result;

    return 0
    }

    int main() {
    float p;
    p=11;
    f( &p);
    cout<<p<<endl;
    return 0;
    }

    Any idea about what I am mistaking?
    thanks a lot
    Roberto
    foice, Jul 27, 2010
    #1
    1. Advertising

  2. foice

    Jonathan Lee Guest

    On Jul 27, 12:27 pm, foice <> wrote:
    > Hello to everybody. I read, and succesfully implented, some example of
    > use of a void* argument to pass a generic type argument to a function.
    > As far as I understand the trick is to recast the pointer to a pointer
    > of the correct type and then use this pointer as usual.
    >
    > int f(void * input) {
    > float * x =(float*) input;
    > flaot value;
    > value=*x
    > cout<<value<<endl;
    >
    > return 0
    >
    > }


    .... er... so you _know_ that input should be a float pointer, but
    you're accepting a void* and then converting, instead of simply
    requiring the correct pointer? ... I hope this is for practice
    or something...

    >
    > Now suppose that I want to compute something can I store this
    > "something" into a void* that is an argument of the function? I tried
    > this, but the value of the variable is not changed, as when I make a
    > cout it gives the same value of the initialization :( .
    >
    > int f(void * argument) {
    >
    > float result;
    > result=0;
    >
    > argument=&result;
    >
    > return 0
    >
    > }


    You're assigning to "argument" rather than "the thing argument
    is pointing to". This is a common mistake when learning about
    pointers.

    Basically, on entry to the function, argument points to p.
    And you'd like p to be changed. But what you're actually
    doing is saying "now let argument point to result".

    The correct notation would usually be

    *argument = result; // the star is a dereference

    but since you have a void* instead of the (correct)
    float* you need a cast:

    float* argument_f = (float*)argument;
    *argument_f = result;

    Again, I hope this is for an exercise, because circumventing
    the type checking mechanism C++ has is generally a bad
    idea.

    --Jonathan
    Jonathan Lee, Jul 27, 2010
    #2
    1. Advertising

  3. foice

    Bo Persson Guest

    foice wrote:
    > Hello to everybody. I read, and succesfully implented, some example
    > of use of a void* argument to pass a generic type argument to a
    > function. As far as I understand the trick is to recast the pointer
    > to a pointer of the correct type and then use this pointer as usual.
    >
    > int f(void * input) {
    > float * x =(float*) input;
    > flaot value;
    > value=*x
    > cout<<value<<endl;
    >
    > return 0
    > }
    >
    > Now suppose that I want to compute something can I store this
    > "something" into a void* that is an argument of the function? I
    > tried this, but the value of the variable is not changed, as when I
    > make a cout it gives the same value of the initialization :( .
    >
    > int f(void * argument) {
    >
    > float result;
    > result=0;
    >
    > argument=&result;
    >
    > return 0
    > }
    >
    > int main() {
    > float p;
    > p=11;
    > f( &p);
    > cout<<p<<endl;
    > return 0;
    > }
    >
    > Any idea about what I am mistaking?
    > thanks a lot
    > Roberto


    Using a void* argument is often a mistake itself. :)

    However, just like you cast the 'input' to a float*, you have to cast
    the 'argument':

    *((float*)argument) = result;


    But if you know that the parameter really is a float*, why complicate
    it this way?


    Bo Persson
    Bo Persson, Jul 27, 2010
    #3
  4. foice

    Jonathan Lee Guest

    On Jul 27, 12:47 pm, Jonathan Lee <> wrote:
    > but since you have a void* instead of the (correct)
    > float* you need a cast:
    >
    >    float* argument_f = (float*)argument;
    >    *argument_f = result;


    Actually, I may as well also mention to drop the whole C-style
    cast and use one of the C++ casts:

    float* argument_f = static_cast<float*>(argument);
    *argument_f = result

    or in one line

    *(static_cast<float*>(argument)) = result;

    --Jonathan
    Jonathan Lee, Jul 27, 2010
    #4
  5. foice

    foice Guest

    On Jul 27, 6:51 pm, "Bo Persson" <> wrote:

    > However, just like you cast the 'input' to a float*, you have to cast
    > the 'argument':
    >
    > *((float*)argument) = result;
    >


    Thank you very much for the reply. This turns out to make my thing
    work. I was confusing the address and the value ...

    About the void* ... Until 3 hours ago I did not even know that one can
    actually use a *void :) and according to your comments I was on the
    way to the heaven of the good coder ... Unfortunately I encountered on
    my way this library to make numerical integration that uses this void*
    to allow you to pass whatever type of variable to the function that
    you want to integrate.

    That's why I cannot avoid using this "dirty" void* ... it is just the
    argument of a function in a library ...

    Thanks again
    Roberto
    foice, Jul 27, 2010
    #5
  6. foice wrote:
    > About the void* ... Until 3 hours ago I did not even know that one can


    No, can not dereference void*

    > actually use a *void :) and according to your comments I was on the
    > way to the heaven of the good coder ... Unfortunately I encountered on


    or a bad coder ;)

    > my way this library to make numerical integration that uses this void*
    > to allow you to pass whatever type of variable to the function that
    > you want to integrate.


    Feel free to throw that book to garbage. Any c++ book that suggests you
    to use void* is bad.
    Vladimir Jovic, Jul 29, 2010
    #6
  7. On 27.07.2010 20:52, Jonathan Lee wrote:
    > On Jul 27, 12:47 pm, Jonathan Lee<> wrote:
    >> but since you have a void* instead of the (correct)
    >> float* you need a cast:
    >>
    >> float* argument_f = (float*)argument;
    >> *argument_f = result;

    >
    > Actually, I may as well also mention to drop the whole C-style
    > cast and use one of the C++ casts:
    >
    > float* argument_f = static_cast<float*>(argument);
    > *argument_f = result
    >
    > or in one line
    >
    > *(static_cast<float*>(argument)) = result;
    >
    > --Jonathan
    >


    if i'm not mistaken it's better to use reinterpret_cast which meaning is
    as it easy to guess reinterpreting the value without any modification
    and runtime overhead.

    I got question too: does (float*) argument and
    static_cast<float*>(argument) produced the same (NONE) code ?

    --
    Ruslan Mullakhmetov
    Ruslan Mullakhmetov, Jul 29, 2010
    #7
  8. foice

    Jonathan Lee Guest

    On Jul 29, 12:13 pm, Ruslan Mullakhmetov <> wrote:
    > On 27.07.2010 20:52, Jonathan Lee wrote:
    > > Actually, I may as well also mention to drop the whole C-style
    > > cast and use one of the C++ casts:
    > >       *(static_cast<float*>(argument)) = result;

    >
    > if i'm not mistaken it's better to use reinterpret_cast which meaning is
    > as it easy to guess reinterpreting the value without any modification
    > and runtime overhead.


    I'm sure both are no-ops in most cases. But static_cast guarantees
    this particular cast is correct (assuming argument was a float*
    originally). This guarantee, plus the likelihood of no performance
    difference, makes me prefer static_cast.

    > I got question too: does (float*) argument and
    > static_cast<float*>(argument) produced the same (NONE) code ?


    I'm sure they produce the _same_ code, though I'd have to check
    the documentation on cast notation (i.e., "C-style cast") to
    be sure that the two are equivalent. But, given that they are
    both casts to pointers of an intrinsic type.. it seems likely.

    Furthermore, this is probably "no code". I can't see, for
    example, void* and float* having different representations on
    x86 machines. I've heard that some CPUs have different
    pointers for floats than chars, which might mean void* has
    a different representation (since it is required to represent
    both). In such a case, code would be generated.

    --Jonathan
    Jonathan Lee, Jul 29, 2010
    #8
  9. foice

    Jonathan Lee Guest

    On Jul 29, 2:09 pm, Pete Becker <> wrote:
    > On 2010-07-29 12:31:32 -0400, Jonathan Lee said:
    > > I'm sure both are no-ops in most cases. But static_cast guarantees
    > > this particular cast is correct (assuming argument was a float*
    > > originally). This guarantee, plus the likelihood of no performance
    > > difference, makes me prefer static_cast.

    >
    > Um, I don't have the original message in front of me, but wasn't
    > argument passed as void*? static_cast makes no guarantee whatsoever
    > that casting void* to some other pointer type is correct. void* has no
    > type information. static_cast does type checking when used on a pointer
    > to an object type to convert to a related object type.


    Hence my qualification: "assuming argument was a float* originally".

    (Not looking at the original message, but I think that was a
    reasonable assumption.)

    [expr.static.cast] guarantees that cvT* -> void* -> cvT* is correct.
    It even gives the example

    T* p1 = new T;
    const T* p2 = static_cast<const T*>(static_cast<void*>(p1));
    bool b = p1 == p2; // b will have the value true

    --Jonathan
    Jonathan Lee, Jul 29, 2010
    #9
  10. foice

    Jonathan Lee Guest

    On Jul 29, 3:17 pm, Pete Becker <> wrote:
    > On 2010-07-29 14:22:16 -0400, Jonathan Lee said:
    > > Hence my qualification: "assuming argument was a float* originally".

    >
    > > (Not looking at the original message, but I think that was a
    > > reasonable assumption.)

    >
    > I guess I'm reacting to "guarantees this particular cast is correct".
    > If argument was a float* in the first place, a C-style cast and a
    > static_cast do exactly the same thing. And if argument was not a float*
    > they also do the same thing. So I don't see what the "guarantee" here
    > is.


    Ah, I see. When I mentioned the guarantee originally, it was in the
    context of static_cast vs reinterpret_cast, i.e., that static_cast
    says this conversion to void* and back is fine, whereas I don't
    believe reinterpret_cast does.

    The general point I was trying to make was to favour the other
    casts over reinterpret_cast, if there was any choice. The bit about
    C-style casts hadn't crept into the discussion at that time.

    --Jonathan
    Jonathan Lee, Jul 29, 2010
    #10
  11. * Pete Becker, on 29.07.2010 21:35:
    > On 2010-07-29 15:28:41 -0400, Jonathan Lee said:
    >
    >> On Jul 29, 3:17 pm, Pete Becker <> wrote:
    >>> On 2010-07-29 14:22:16 -0400, Jonathan Lee said:
    >>>> Hence my qualification: "assuming argument was a float* originally".
    >>>
    >>>> (Not looking at the original message, but I think that was a
    >>>> reasonable assumption.)
    >>>
    >>> I guess I'm reacting to "guarantees this particular cast is correct".
    >>> If argument was a float* in the first place, a C-style cast and a
    >>> static_cast do exactly the same thing. And if argument was not a float*
    >>> they also do the same thing. So I don't see what the "guarantee" here
    >>> is.

    >>
    >> Ah, I see. When I mentioned the guarantee originally, it was in the
    >> context of static_cast vs reinterpret_cast, i.e., that static_cast
    >> says this conversion to void* and back is fine, whereas I don't
    >> believe reinterpret_cast does.
    >>
    >> The general point I was trying to make was to favour the other
    >> casts over reinterpret_cast, if there was any choice. The bit about
    >> C-style casts hadn't crept into the discussion at that time.
    >>

    >
    > Okay, so I muddled things with my automatic reaction that when someone
    > talks about guarantees they're contrasting with a C-style cast. You're
    > absolutely right, of course: the result of a round-trip conversion
    > through a reinterpert_cast<void*> is unspecified.


    A reinterpret_cast roundtrip conversion through void* is not unspecified, but is
    guaranteed to yield the original pointer, by §5.2.10/7 (and §3.9.2/4).


    Cheers & hth.,

    - Alf

    --
    blog at <url: http://alfps.wordpress.com>
    Alf P. Steinbach /Usenet, Jul 29, 2010
    #11
  12. * Pete Becker, on 30.07.2010 01:22:
    > On 2010-07-29 18:17:55 -0400, Alf P. Steinbach /Usenet said:
    >
    >> * Pete Becker, on 29.07.2010 21:35:
    >>> On 2010-07-29 15:28:41 -0400, Jonathan Lee said:
    >>>
    >>>> On Jul 29, 3:17 pm, Pete Becker <> wrote:
    >>>>> On 2010-07-29 14:22:16 -0400, Jonathan Lee said:
    >>>>>> Hence my qualification: "assuming argument was a float* originally".
    >>>>>
    >>>>>> (Not looking at the original message, but I think that was a
    >>>>>> reasonable assumption.)
    >>>>>
    >>>>> I guess I'm reacting to "guarantees this particular cast is correct".
    >>>>> If argument was a float* in the first place, a C-style cast and a
    >>>>> static_cast do exactly the same thing. And if argument was not a
    >>>>> float*
    >>>>> they also do the same thing. So I don't see what the "guarantee" here
    >>>>> is.
    >>>>
    >>>> Ah, I see. When I mentioned the guarantee originally, it was in the
    >>>> context of static_cast vs reinterpret_cast, i.e., that static_cast
    >>>> says this conversion to void* and back is fine, whereas I don't
    >>>> believe reinterpret_cast does.
    >>>>
    >>>> The general point I was trying to make was to favour the other
    >>>> casts over reinterpret_cast, if there was any choice. The bit about
    >>>> C-style casts hadn't crept into the discussion at that time.
    >>>>
    >>>
    >>> Okay, so I muddled things with my automatic reaction that when someone
    >>> talks about guarantees they're contrasting with a C-style cast. You're
    >>> absolutely right, of course: the result of a round-trip conversion
    >>> through a reinterpert_cast<void*> is unspecified.

    >>
    >> A reinterpret_cast roundtrip conversion through void* is not
    >> unspecified, but is guaranteed to yield the original pointer, by
    >> §5.2.10/7 (and §3.9.2/4).
    >>

    >
    > 5.2.10/7 (second sentence):
    >
    > Except that converting an rvalue of type “pointer to T1†to the type
    > “pointer to T2â€
    > (where T1 and T2 are object types and where the alignment requirements
    > of T2
    > are no stricter than those of T1) and back to its original type yields
    > the original
    > pointer value, the result of such a pointer conversion is unspecified.
    >
    > void is not an object type, so void* does not meet the requirements in
    > parentheses.


    Right, I didn't see that.

    But there is already a known defect that sentence, namely direct contradiction
    between its "Except that ..., the result ... is unspecified", and §9.2/17, "A
    pointer to a POD-struct object, suitably converted using reinterpret_cast,
    points to its initial member (or if that member is a bit-field, then to the unit
    in which it resides) and vice versa", which is at least one more case where the
    result /is/ specified.

    And that sentence would, with literal interpretation, force round-trip
    conversion guarantee for all object pointer types (of suitable alignment) as
    intermediary, but not for void*, where the compiler would be free to sort of
    mess up things by always producing the nullpointer value, say.

    As I see it that can't have been the intention, since it is absurd and of no
    practical value.

    And the existing defect in the same sentence means that it does suffer from
    known lack of rigorousness, hence more likely that the absurdity is a defect,
    and not the result of moronic intention, yes? :)


    > The result is unspecified.


    Yeah, now you point it out I agree that it's formally unspecified -- *but*,
    that's IMO a defect. Anyway, it's absurd. The standard isn't about providing
    means and ways of the compiler messing up things in malicious ways.


    > Note that 3.9.2/4 does not say that void* is a pointer to object type;
    > rather, it says that void* can be used to point to an object of unknown
    > type.


    Yes, I understood that.


    Cheers & hth., & thanks,

    - Alf

    --
    blog at <url: http://alfps.wordpress.com>
    Alf P. Steinbach /Usenet, Jul 30, 2010
    #12
  13. On 29.07.2010 20:31, Jonathan Lee wrote:
    > Furthermore, this is probably "no code". I can't see, for
    > example, void* and float* having different representations on
    > x86 machines. I've heard that some CPUs have different
    > pointers for floats than chars, which might mean void* has
    > a different representation (since it is required to represent
    > both). In such a case, code would be generated.
    >

    thanks, i've known that C++ guarantee that all pointers to any objects
    are of the same size but didn't take into account that it can be the
    largest possible pointer on target platform.

    by the way, yesterday i turned over the pages of Satters' book
    (exceptional C++) and found his note that С++ type casting operators
    were chosen to be long enough with the purpose to make their use more
    complicated (and force programmers to doubt their use necessity).

    --
    Ruslan Mullakhmetov
    Ruslan Mullakhmetov, Jul 30, 2010
    #13
  14. foice

    James Kanze Guest

    On Jul 30, 1:51 am, "Alf P. Steinbach /Usenet" <alf.p.steinbach
    > wrote:
    > * Pete Becker, on 30.07.2010 01:22:


    [...]
    > >> A reinterpret_cast roundtrip conversion through void* is not
    > >> unspecified, but is guaranteed to yield the original pointer, by
    > >> §5.2.10/7 (and §3.9.2/4).


    > > 5.2.10/7 (second sentence):


    > > Except that converting an rvalue of type “pointer to T1” to
    > > the type “pointer to T2” (where T1 and T2 are object types
    > > and where the alignment requirements of T2 are no stricter
    > > than those of T1) and back to its original type yields the
    > > original pointer value, the result of such a pointer
    > > conversion is unspecified.


    > > void is not an object type, so void* does not meet the requirements in
    > > parentheses.


    > Right, I didn't see that.


    > But there is already a known defect that sentence, namely
    > direct contradiction between its "Except that ..., the result
    > ... is unspecified", and §9.2/17, "A pointer to a POD-struct
    > object, suitably converted using reinterpret_cast, points to
    > its initial member (or if that member is a bit-field, then to
    > the unit in which it resides) and vice versa", which is at
    > least one more case where the result /is/ specified.


    > And that sentence would, with literal interpretation, force
    > round-trip conversion guarantee for all object pointer types
    > (of suitable alignment) as intermediary,


    I don't see where you read that. The first element of
    a POD-struct object must have have the same address as the
    complete object, which means that it must be suitably aligned
    for the complete object. Consider the case of a word addressed
    machine, where char* contains extra information specifying the
    byte in the word. The address of a POD-struct type (or int, or
    anything but a char type) doesn't contain this information.
    Converting a char* to some other pointer type, then back, looses
    this information, so the resulting char* would point to the
    first char in the word, and not the char it originally pointed
    to. If the first element in the POD-struct is a char, however,
    it is the first char in the first word of the POD-struct, so the
    results still satisfy the requirements.

    > but not for void*,
    > where the compiler would be free to sort of mess up things by
    > always producing the nullpointer value, say.


    Except that void* is guaranteed to have the same size and
    representation as char*, so any guarantees for char* sort of
    apply to void* as well. (I think. The guarantee concerning the
    same size and representation were present in C; I presume that
    C++ makes the same guarantee.)

    --
    James Kanze
    James Kanze, Jul 30, 2010
    #14
  15. * James Kanze, on 30.07.2010 12:18:
    > On Jul 30, 1:51 am, "Alf P. Steinbach /Usenet"<alf.p.steinbach
    > > wrote:
    >> * Pete Becker, on 30.07.2010 01:22:

    >
    > [...]
    >>>> A reinterpret_cast roundtrip conversion through void* is not
    >>>> unspecified, but is guaranteed to yield the original pointer, by
    >>>> §5.2.10/7 (and §3.9.2/4).

    >
    >>> 5.2.10/7 (second sentence):

    >
    >>> Except that converting an rvalue of type “pointer to T1” to
    >>> the type “pointer to T2” (where T1 and T2 are object types
    >>> and where the alignment requirements of T2 are no stricter
    >>> than those of T1) and back to its original type yields the
    >>> original pointer value, the result of such a pointer
    >>> conversion is unspecified.

    >
    >>> void is not an object type, so void* does not meet the requirements in
    >>> parentheses.

    >
    >> Right, I didn't see that.

    >
    >> But there is already a known defect that sentence, namely
    >> direct contradiction between its "Except that ..., the result
    >> ... is unspecified", and §9.2/17, "A pointer to a POD-struct
    >> object, suitably converted using reinterpret_cast, points to
    >> its initial member (or if that member is a bit-field, then to
    >> the unit in which it resides) and vice versa", which is at
    >> least one more case where the result /is/ specified.

    >
    >> And that sentence would, with literal interpretation, force
    >> round-trip conversion guarantee for all object pointer types
    >> (of suitable alignment) as intermediary,

    >
    > I don't see where you read that.


    5.2.10/7 (second sentence), it's what it specifies.


    > The first element of
    > a POD-struct object must have have the same address as the
    > complete object, which means that it must be suitably aligned
    > for the complete object. Consider the case of a word addressed
    > machine, where char* contains extra information specifying the
    > byte in the word. The address of a POD-struct type (or int, or
    > anything but a char type) doesn't contain this information.
    > Converting a char* to some other pointer type, then back, looses
    > this information, so the resulting char* would point to the
    > first char in the word, and not the char it originally pointed
    > to.


    Yeah, that's what my "of suitable alignment" is about.

    It seems that you violently agree with me. :)


    > If the first element in the POD-struct is a char, however,
    > it is the first char in the first word of the POD-struct, so the
    > results still satisfy the requirements.


    >> but not for void*,
    >> where the compiler would be free to sort of mess up things by
    >> always producing the nullpointer value, say.


    Regarding this statement, I was a bit hasty: the compiler is only free to mess
    up things if the original object is not a POD struct or first member of such. It
    seems a very peculiar license to mess up, very arbitrary; but I think is just
    defect.


    > Except that void* is guaranteed to have the same size and
    > representation as char*, so any guarantees for char* sort of
    > apply to void* as well. (I think. The guarantee concerning the
    > same size and representation were present in C; I presume that
    > C++ makes the same guarantee.)


    Yeah. As mentioned, this seems to be an additional defect in /the same
    sentence/, that is, 5.2.10/7 (second sentence).


    Cheers,

    - Alf

    --
    blog at <url: http://alfps.wordpress.com>
    Alf P. Steinbach /Usenet, Jul 30, 2010
    #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:
    494
    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:
    767
    The Real OS/2 Guy
    Oct 28, 2003
  3. Replies:
    5
    Views:
    806
    S.Tobias
    Jul 22, 2005
  4. Replies:
    1
    Views:
    384
    Victor Bazarov
    May 23, 2007
  5. Michael Tan
    Replies:
    32
    Views:
    908
    Ara.T.Howard
    Jul 21, 2005
Loading...

Share This Page