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
... 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
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
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
> 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
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.
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
>
> I got question too: does (float*) argument and
> static_cast<float*>(argument) produced the same (NONE) code ?
Yes.
--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)
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
> On Jul 29, 12:13 pm, Ruslan Mullakhmetov <tiaba...@gmail.com> 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.
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
> On Jul 29, 2:09 pm, Pete Becker <p...@versatilecoding.com> 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.)
>
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
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>
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. The result is unspecified.
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.
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,
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
[...]
> >> 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
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,