digitalmars.D - Casting Pointers?
- John Burton (12/12) May 12 2016 I've been unable to find a clear definitive answer to this so
- ZombineDev (4/16) May 12 2016 Yes, it's perfectly legal in @system code, but only if you know
- Stefan Koch (2/14) May 12 2016 How would such a cast be safe?
- Rene Zwanenburg (2/3) May 12 2016 I'm guessing safe as in defined behavior.
- John Burton (8/28) May 12 2016 "Safe" as in it produces a valid long value by interpreting the
- Rene Zwanenburg (14/16) May 12 2016 Phobos / druntime use casts like this as well, but there has been
- Marco Leise (6/16) May 12 2016 The pointer cast solution is specifically supported at CTFE,
- Rene Zwanenburg (8/20) May 13 2016 Well that's a problem ^^
- Dicebot (3/5) May 12 2016 We rely on this cast to be legal and well-defined in a lot of
- Dicebot (3/8) May 12 2016 (most common case is casting between `char[]` and `struct S {
- H. S. Teoh via Digitalmars-d (6/11) May 12 2016 Does alias this solve the problem, or it introduces new ones?
- Dicebot (10/11) May 12 2016 void foo ( ref char[] x )
- Johannes Pfau (13/23) May 12 2016 That cast is safe even with strict aliasing rules:
- H. S. Teoh via Digitalmars-d (15/31) May 12 2016 AFAIK this is legal in D, though it does break @safe-ty so it can only
- Anon (14/26) May 12 2016 This is a Bad Idea in C because types in C aren't actually
I've been unable to find a clear definitive answer to this so please point me to one if it already exists in the manual or the forums. Is it safe to cast pointer types? double data; long p = *cast(long*)&data; (Excuse any silly syntax errors as I'm doing this on my phone). This used to be possible in C until people recently decided it not only was wrong, it had always been wrong :P (Ok I'm not entirely serious there but that's what this issue feels like...) Is this legal / valid in D and if not what is the appropriate way to efficiently access data like this?
May 12 2016
On Thursday, 12 May 2016 at 08:41:25 UTC, John Burton wrote:I've been unable to find a clear definitive answer to this so please point me to one if it already exists in the manual or the forums. Is it safe to cast pointer types? double data; long p = *cast(long*)&data; (Excuse any silly syntax errors as I'm doing this on my phone). This used to be possible in C until people recently decided it not only was wrong, it had always been wrong :P (Ok I'm not entirely serious there but that's what this issue feels like...) Is this legal / valid in D and if not what is the appropriate way to efficiently access data like this?Yes, it's perfectly legal in system code, but only if you know what you're doing ;) Take a look at std.math for example: https://github.com/dlang/phobos/blob/v2.071.0/std/math.d#L4839
May 12 2016
On Thursday, 12 May 2016 at 08:41:25 UTC, John Burton wrote:I've been unable to find a clear definitive answer to this so please point me to one if it already exists in the manual or the forums. Is it safe to cast pointer types? double data; long p = *cast(long*)&data; (Excuse any silly syntax errors as I'm doing this on my phone). This used to be possible in C until people recently decided it not only was wrong, it had always been wrong :P (Ok I'm not entirely serious there but that's what this issue feels like...) Is this legal / valid in D and if not what is the appropriate way to efficiently access data like this?How would such a cast be safe?
May 12 2016
On Thursday, 12 May 2016 at 09:25:49 UTC, Stefan Koch wrote:How would such a cast be safe?I'm guessing safe as in defined behavior.
May 12 2016
On Thursday, 12 May 2016 at 09:25:49 UTC, Stefan Koch wrote:On Thursday, 12 May 2016 at 08:41:25 UTC, John Burton wrote:"Safe" as in it produces a valid long value by interpreting the bytes of the stored double. Obviously if it works it's very system dependent. But in C it's simply undefined behavior to read a value stored using one pointer type using a pointer to a different type. (With some additional rules about char in a few cases). The whole strict aliasing businesssI've been unable to find a clear definitive answer to this so please point me to one if it already exists in the manual or the forums. Is it safe to cast pointer types? double data; long p = *cast(long*)&data; (Excuse any silly syntax errors as I'm doing this on my phone). This used to be possible in C until people recently decided it not only was wrong, it had always been wrong :P (Ok I'm not entirely serious there but that's what this issue feels like...) Is this legal / valid in D and if not what is the appropriate way to efficiently access data like this?How would such a cast be safe?
May 12 2016
On Thursday, 12 May 2016 at 08:41:25 UTC, John Burton wrote:Is this legal / valid in D and if not what is the appropriate way to efficiently access data like this?Phobos / druntime use casts like this as well, but there has been some discussion as to whether it should be guaranteed to be correct. There are good reasons the C folks disallow it (well, performance of course, what else? ^^), and the reasoning applies to D as well. In this case, you can use a union: union DL { double d; long l; } auto dl = DL(1.0); writeln(dl.l);
May 12 2016
Am Thu, 12 May 2016 09:32:17 +0000 schrieb Rene Zwanenburg <renezwanenburg gmail.com>:In this case, you can use a union: union DL { double d; long l; } auto dl = DL(1.0); writeln(dl.l);The pointer cast solution is specifically supported at CTFE, because /unions/ don't work there. :p -- Marco
May 12 2016
On Thursday, 12 May 2016 at 22:23:38 UTC, Marco Leise wrote:The pointer cast solution is specifically supported at CTFE, because /unions/ don't work there. :pWell that's a problem ^^ I remember a discussion quite a while ago where Walter stated D should have strict aliasing rules, let me see if I can find it.. Ah here: http://forum.dlang.org/post/jg3f21$1jqa$1 digitalmars.com On Saturday, 27 July 2013 at 06:58:04 UTC, Walter Bright wrote:Although it isn't in the spec, D should be "strict aliasing". This is because: 1. it enables better code generation 2. there are ways, such as unions, to get the other aliasing that doesn't break strict aliasingOn Saturday, 27 July 2013 at 08:59:54 UTC, Walter Bright wrote:On 7/27/2013 1:57 AM, David Nadlinger wrote:We need to carefully formalize this then, and quickly. [...]I agree. Want to do an enhancement request on bugzilla for it?
May 13 2016
On Thursday, 12 May 2016 at 08:41:25 UTC, John Burton wrote:Is this legal / valid in D and if not what is the appropriate way to efficiently access data like this?We rely on this cast to be legal and well-defined in a lot of Sociomantic code, banning would be a real disaster :X
May 12 2016
On Thursday, 12 May 2016 at 09:33:54 UTC, Dicebot wrote:On Thursday, 12 May 2016 at 08:41:25 UTC, John Burton wrote:(most common case is casting between `char[]` and `struct S { char[]; }`)Is this legal / valid in D and if not what is the appropriate way to efficiently access data like this?We rely on this cast to be legal and well-defined in a lot of Sociomantic code, banning would be a real disaster :X
May 12 2016
On Thu, May 12, 2016 at 09:38:27AM +0000, Dicebot via Digitalmars-d wrote:On Thursday, 12 May 2016 at 09:33:54 UTC, Dicebot wrote:[...]Does alias this solve the problem, or it introduces new ones? T -- Let's eat some disquits while we format the biskettes.We rely on this cast to be legal and well-defined in a lot of Sociomantic code, banning would be a real disaster :X(most common case is casting between `char[]` and `struct S { char[]; }`)
May 12 2016
On Thursday, 12 May 2016 at 14:20:28 UTC, H. S. Teoh wrote:Does alias this solve the problem, or it introduces new ones?void foo ( ref char[] x ) { static assert (x.sizeof == Wrapper.sizeof); (cast(Wrapper*) &x).someMethod(); // may resize x } Not sure how alias this can be applicable here. One recurring reason to write code like this is when one replaces plain type with more type-safe wrapper but wants to keep old API working with raw arrays as deprecated.
May 12 2016
Am Thu, 12 May 2016 09:38:27 +0000 schrieb Dicebot <public dicebot.lv>:On Thursday, 12 May 2016 at 09:33:54 UTC, Dicebot wrote:That cast is safe even with strict aliasing rules: http://stackoverflow.com/questions/9747010/does-accessing-the-first-field-of-a-struct-via-a-c-cast-violate-strict-aliasing So it's highly unlikely this will ever become undefined behavior in D :-) In the end a compiler writers can make up arbitrary aliasing rules: For example in D ubyte[] should probably alias all [] slices, ubyte* aliases all pointers (like char* in C), ... double and long are fundamentally different though, so aliasing wouldn't be allowed for these types in most languages. AFAIK no D compiler actually enforces strict aliasing right now. GDC explicitly disables all aliasing related optimizations.On Thursday, 12 May 2016 at 08:41:25 UTC, John Burton wrote:(most common case is casting between `char[]` and `struct S { char[]; }`)Is this legal / valid in D and if not what is the appropriate way to efficiently access data like this?We rely on this cast to be legal and well-defined in a lot of Sociomantic code, banning would be a real disaster :X
May 12 2016
On Thu, May 12, 2016 at 08:41:25AM +0000, John Burton via Digitalmars-d wrote:I've been unable to find a clear definitive answer to this so please point me to one if it already exists in the manual or the forums. Is it safe to cast pointer types? double data; long p = *cast(long*)&data; (Excuse any silly syntax errors as I'm doing this on my phone). This used to be possible in C until people recently decided it not only was wrong, it had always been wrong :P (Ok I'm not entirely serious there but that's what this issue feels like...) Is this legal / valid in D and if not what is the appropriate way to efficiently access data like this?AFAIK this is legal in D, though it does break safe-ty so it can only be used in system code. An alternative is to use a union: long reinterpretAsLong(double data) safe { union U { double d; long l; } U u; u.d = data; return u.l; } A bit verbose, but disassembly shows that the dmd -O is able to reduce it to a single mov instruction, as it should be. T -- English is useful because it is a mess. Since English is a mess, it maps well onto the problem space, which is also a mess, which we call reality. Similarly, Perl was designed to be a mess, though in the nicest of all possible ways. -- Larry Wall
May 12 2016
On Thursday, 12 May 2016 at 08:41:25 UTC, John Burton wrote:I've been unable to find a clear definitive answer to this so please point me to one if it already exists in the manual or the forums. Is it safe to cast pointer types? double data; long p = *cast(long*)&data; (Excuse any silly syntax errors as I'm doing this on my phone). This used to be possible in C until people recently decided it not only was wrong, it had always been wrong :P (Ok I'm not entirely serious there but that's what this issue feels like...)This is a Bad Idea in C because types in C aren't actually well-defined. `long` is required to be at least 32 bits. `double` is required to be a floating point type. They will often not match up in sizes the way you might think. The spec doesn't even require `double` to be IEEE (that's an optional annex). Clang on Linux x86_64 has both `long` and `double` as 64-bit types. Clang on Linux x86 has `long` as 32-bit, `double` as 64-bit.Is this legal / valid in D and if not what is the appropriate way to efficiently access data like this?In D, both `long` and `double` are defined in the spec to be 64-bits, regardless of compiler/os/arch. It isn't "safe" (because casting pointers is never safe), but it should behave predictably. Note that D does have its own poorly-defined types, such as `real`, that you will need to be careful with.
May 12 2016