|
Boost : |
Subject: Re: [boost] [AFIO] Formal review
From: John Bytheway (jbytheway+boost_at_[hidden])
Date: 2015-09-04 07:47:03
On 2015-09-04 05:52, John Bytheway wrote:
> On 2015-09-02 14:55, Niall Douglas wrote:
>> On 2 Sep 2015 at 5:31, John Bytheway wrote:
>>
>>>> Please do correct me if I am wrong, but I had thought that this is
>>>> defined behaviour:
>>>>
>>>> int a=5;
>>>> void *b=(void *)(size_t) a;
>>>> int c=(int)(size_t) b;
>>>> assert(c==a);
>>>>
>>>> This is certainly a very common pattern in C.
>>>
>>> I believe this is implementation-defined. Based on N3797
>>> [expr.reinterpret.cast], paragraph 5:
>>>
>>> "A value of integral type or enumeration type can be explicitly
>>> converted to a pointer. A pointer converted to an integer of sufficient
>>> size (if any such exists on the implementation) and back to the same
>>> pointer type will have its original value; mappings between pointers and
>>> integers are otherwise implementation-defined."
>>>
>>> The behaviour that is defined (pointer to integer and back) is the
>>> reverse of the one you want.
>>
>> That's the whole point of the intermediate size_t cast. int to size_t
>> is defined behaviour, size_t to void * is defined behaviour, void *
>> to size_t is defined behaviour, size_t to int is defined behaviour.
>
> To be clear, do you mean standard-defined (as opposed to
> implementation-defined)? I'm assuming so.
>
> Then, as Andrey pointed out, the result is not defined. Only integer
> values that were obtained from a previous cast from a pointer can be
> safely cast to a pointer type (unless you have evidence from elsewhere
> in the standard to suggest more).
>
> If you actually want defined behaviour here, I think you should use a
> union { int; void*; }. That ought not to have any performance penalty.
I realised that this comment was ambiguous. To clarify: I do *not* mean
using a union for type-punning to convert the int to a void*; rather I
mean using a union as the native handle type so you never need to
convert the int to a void*.
John
> That said, I imagine that in practice the implementation-defined
> behaviour of what you're doing will be what you want in any
> implementation where using AFIO makes sense.
>
> John
>
>> Older code, and still a lot of C code, directly casts between int and
>> void * and back again, even though strictly speaking that's a no no.
>>
>> Niall
>>
>>
>>
>>
>> _______________________________________________
>> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
>>
>
>
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
>
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk