www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Casting pointers

reply "John Burton" <john.burton jbmail.com> writes:
This would be undefined behavior in c++ due to aliasing rules on 
pointers. It appears to "work" reliably in D when I try it, but 
that's obviously no guarantee that it's correct or will continue 
to do so.

Is this correct code in D? And if not, what should I do instead 
to cleanly and efficiently extract structured data from a 
sequence of bytes?

import std.stdio;

struct data
{
     int a;
     int b;
}

void main()
{
     byte[] x = [1, 2, 3, 4, 5, 6, 7, 8];

     data* ptr = cast(data*)(x);
     printf("%x %x\n", ptr.a, ptr.b);

}
Aug 26 2015
next sibling parent reply anonymous <anonymous example.com> writes:
On Wednesday 26 August 2015 14:14, John Burton wrote:

 This would be undefined behavior in c++ due to aliasing rules on
 pointers. It appears to "work" reliably in D when I try it, but
 that's obviously no guarantee that it's correct or will continue
 to do so.
 
 Is this correct code in D? And if not, what should I do instead
 to cleanly and efficiently extract structured data from a
 sequence of bytes?
 
 import std.stdio;
 
 struct data
 {
      int a;
      int b;
 }
 
 void main()
 {
      byte[] x = [1, 2, 3, 4, 5, 6, 7, 8];
 
      data* ptr = cast(data*)(x);
      printf("%x %x\n", ptr.a, ptr.b);
 
 }
There's an open issue about it: https://issues.dlang.org/show_bug.cgi?id=10750 I don't know where we stand exactly, but by the looks of it, strict aliasing has never been added to the spec. So compilers should not assume it. As David Nadlinger points out: "There is already quite a lot of D code out there that violates the C-style strict aliasing rules." I think that code should be fine for now. If it isn't, we have a problem, because with a silent spec we have no way of knowing what alternatives should work.
Aug 26 2015
parent "John Burton" <john.burton jbmail.com> writes:
Ok thank you.

Seems to me that there is enough doubt that this is "supported" 
that I'd be best to avoid relying on it, or at least ensure that 
it's all encapsulated in something I can easily change.
Aug 27 2015
prev sibling next sibling parent "Gary Willoughby" <dev nomad.so> writes:
On Wednesday, 26 August 2015 at 12:14:54 UTC, John Burton wrote:
 This would be undefined behavior in c++ due to aliasing rules 
 on pointers. It appears to "work" reliably in D when I try it, 
 but that's obviously no guarantee that it's correct or will 
 continue to do so.

 Is this correct code in D? And if not, what should I do instead 
 to cleanly and efficiently extract structured data from a 
 sequence of bytes?

 import std.stdio;

 struct data
 {
     int a;
     int b;
 }

 void main()
 {
     byte[] x = [1, 2, 3, 4, 5, 6, 7, 8];

     data* ptr = cast(data*)(x);
     printf("%x %x\n", ptr.a, ptr.b);

 }
This would perhaps be safer: import std.stdio; struct Data { int a; int b; } void main() { byte[] x = [1, 2, 3, 4, 5, 6, 7, 8]; Data* data = cast(Data*)(x[0..Data.sizeof].ptr); printf("%x %x\n", data.a, data.b); }
Aug 27 2015
prev sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 8/26/15 8:14 AM, John Burton wrote:
 This would be undefined behavior in c++ due to aliasing rules on
 pointers. It appears to "work" reliably in D when I try it, but that's
 obviously no guarantee that it's correct or will continue to do so.

 Is this correct code in D? And if not, what should I do instead to
 cleanly and efficiently extract structured data from a sequence of bytes?

 import std.stdio;

 struct data
 {
      int a;
      int b;
 }

 void main()
 {
      byte[] x = [1, 2, 3, 4, 5, 6, 7, 8];

      data* ptr = cast(data*)(x);
      printf("%x %x\n", ptr.a, ptr.b);

 }
This should be defined behavior (but there is an issue that will probably eventually be fixed -- you shouldn't cast an array to a pointer, use x.ptr instead). I think strict aliasing only comes into play when something is *changed*. For example: byte[] x = [1, 2, 3, 4, 5, 6, 7, 8]; data* ptr = cast(data *)(x.ptr); ptr.a = 4; writefln("%x %x\n", x[0], x[1]); However, if we consider the strict aliasing rule from C++ allows casting to char * and unsigned char *, D's byte[] and ubyte[] should be equivalent to those. So if anything, that should be defined. -Steve
Aug 27 2015