digitalmars.D - reinterpret_cast or something...
- nod (11/11) Mar 20 2005 Is there a good reason why the following should not be allowed:
- Ben Hinkle (15/29) Mar 20 2005 The cast is illegal because char[] contains both the ptr and length and ...
- nod (38/51) Mar 20 2005 Indeed, it makes sense from that perspective, though it doesn't help the
- Ben Hinkle (7/24) Mar 20 2005 Oh - you want the _contents_ of the array to be cast. I missed that part...
- Lukas Pinkowski (3/30) Mar 20 2005 You're dereferencing the wrong pointer, it should be
- Derek Parnell (25/40) Mar 20 2005 Agreed, it does get a bit confusing at times, but the phrase 'buf[0..4]'...
- Walter (6/17) Mar 20 2005 and
Is there a good reason why the following should not be allowed: --- char[] buf; // ...read into buf... uint32_t fourcc = cast(uint32_t) buf[0..4]; --- The values are the same size, and the code clearly shows my intention to reinterpret the byte data as an integer value. I could cast to pointers and back, but that's kind of roundabout and then I lose automatic bounds checking. Ah well.. There's probably an easy way I haven't thought of yet. Do enlighten me.
Mar 20 2005
"nod" <nod_member pathlink.com> wrote in message news:d1kn6g$19a3$1 digitaldaemon.com...Is there a good reason why the following should not be allowed: --- char[] buf; // ...read into buf... uint32_t fourcc = cast(uint32_t) buf[0..4]; --- The values are the same size, and the code clearly shows my intention to reinterpret the byte data as an integer value. I could cast to pointers and back, but that's kind of roundabout and then I lose automatic bounds checking. Ah well.. There's probably an easy way I haven't thought of yet. Do enlighten me.The cast is illegal because char[] contains both the ptr and length and so a uint can't fit both pieces of data. For example one wouldn't expect the following to work: struct big { char* ptr; uint length; } ... big x; cast(uint)x; For your particular example you can write uint32_t fourcc = cast(uint32_t) buf[0..4].ptr; -Ben
Mar 20 2005
In article <d1knja$19n3$1 digitaldaemon.com>, Ben Hinkle says...The cast is illegal because char[] contains both the ptr and length and so a uint can't fit both pieces of data. For example one wouldn't expect the following to work: struct big { char* ptr; uint length; } ... big x; cast(uint)x;Indeed, it makes sense from that perspective, though it doesn't help the intuitiveness of the language. If I have four bytes on each side of the expression and an explicit cast, it should just work.For your particular example you can write uint32_t fourcc = cast(uint32_t) buf[0..4].ptr; -BenExcellent! But it doesn't work :) Even after actually dereferencing the pointer, *cough*, I get some peculiar results. --- import std.stdio; // for printf import std.string; // for toStringz alias toStringz sz; int main (char[][] args) { char[] a = "alpha"; char[] z = "zebra"; printf("S: %s, I: %u P: %u\n", sz( a ), cast(uint) *a.ptr, cast(uint) a.ptr ); printf("S: %s, I: %u P: %u\n", sz( z ), cast(uint) *z.ptr, cast(uint) z.ptr ); printf("S: %s, I: %u P: %u\n", sz( a[0..4] ), cast(uint) *a[0..4].ptr, cast(uint) a[0..4].ptr ); printf("S: %s, I: %u P: %u\n", sz( z[0..4] ), cast(uint) *z[0..4].ptr, cast(uint) z[0..4].ptr ); return 0; } --- Results for DMD 1.181: #S: alpha, I: 5 P: 134567604 #S: zebra, I: 5 P: 134567620 #S: alph, I: 4 P: 134567604 #S: zebr, I: 4 P: 134567620 #Segmentation fault Results for GDC 0.10: #S: alpha, I: 97 P: 134566344 #S: zebra, I: 122 P: 134566350 #S: alph, I: 97 P: 134566344 #S: zebr, I: 122 P: 134566350 Am I venturing into the Twilight Zone here?
Mar 20 2005
"nod" <nod_member pathlink.com> wrote in message news:d1kucp$1fup$1 digitaldaemon.com...In article <d1knja$19n3$1 digitaldaemon.com>, Ben Hinkle says...Oh - you want the _contents_ of the array to be cast. I missed that part. The expression buf[0..4] creates another dynamic array so I thought you were trying to cast the array ptr to an int. In order to get the contents you need to do something like uint fourcc = *(cast(uint*)buf.ptr)The cast is illegal because char[] contains both the ptr and length and so a uint can't fit both pieces of data. For example one wouldn't expect the following to work: struct big { char* ptr; uint length; } ... big x; cast(uint)x;Indeed, it makes sense from that perspective, though it doesn't help the intuitiveness of the language. If I have four bytes on each side of the expression and an explicit cast, it should just work.
Mar 20 2005
nod wrote:You're dereferencing the wrong pointer, it should be uint fourcc = *(cast(uint*) buf[0..4].ptr);For your particular example you can write uint32_t fourcc = cast(uint32_t) buf[0..4].ptr;Excellent! But it doesn't work :) Even after actually dereferencing the pointer, *cough*, I get some peculiar results.--- import std.stdio; // for printf import std.string; // for toStringz alias toStringz sz; int main (char[][] args) { char[] a = "alpha"; char[] z = "zebra"; printf("S: %s, I: %u P: %u\n", sz( a ), cast(uint) *a.ptr, cast(uint) a.ptr ); printf("S: %s, I: %u P: %u\n", sz( z ), cast(uint) *z.ptr, cast(uint) z.ptr ); printf("S: %s, I: %u P: %u\n", sz( a[0..4] ), cast(uint) *a[0..4].ptr, cast(uint) a[0..4].ptr ); printf("S: %s, I: %u P: %u\n", sz( z[0..4] ), cast(uint) *z[0..4].ptr, cast(uint) z[0..4].ptr ); return 0; }
Mar 20 2005
Lukas Pinkowski wrote:You're dereferencing the wrong pointer, it should be uint fourcc = *(cast(uint*) buf[0..4].ptr);Umm yes, that's true. NTS: Never code when tired. Ben Hinkle wrote:Oh - you want the _contents_ of the array to be cast. I missed that part. The expression buf[0..4] creates another dynamic array so I thought you were trying to cast the array ptr to an int. In order to get the contents you need to do something like uint fourcc = *(cast(uint*)buf.ptr)Actually, what I would really like is a reference. Are there even references to scalars in D? Lukas Pinkowski, Ben Hinkle and Walter wrote:uint fourcc = *cast(uint *)buf.ptr;Yup I have figured that out by now. Thanks!
Mar 21 2005
You can use the pointer (which is about the same as a reference), or you can create a slice to get a bounds-checked array of size 1 (int[] arr=ptr[0..1]), or .. Depends on what you want to do with it.. xs0 nod wrote:Lukas Pinkowski wrote:You're dereferencing the wrong pointer, it should be uint fourcc = *(cast(uint*) buf[0..4].ptr);Umm yes, that's true. NTS: Never code when tired. Ben Hinkle wrote:Oh - you want the _contents_ of the array to be cast. I missed that part. The expression buf[0..4] creates another dynamic array so I thought you were trying to cast the array ptr to an int. In order to get the contents you need to do something like uint fourcc = *(cast(uint*)buf.ptr)Actually, what I would really like is a reference. Are there even references to scalars in D? Lukas Pinkowski, Ben Hinkle and Walter wrote:uint fourcc = *cast(uint *)buf.ptr;Yup I have figured that out by now. Thanks!
Mar 21 2005
On Sun, 20 Mar 2005 20:41:52 +0000 (UTC), nod wrote:Is there a good reason why the following should not be allowed: --- char[] buf; // ...read into buf... uint32_t fourcc = cast(uint32_t) buf[0..4]; --- The values are the same size, and the code clearly shows my intention to reinterpret the byte data as an integer value. I could cast to pointers and back, but that's kind of roundabout and then I lose automatic bounds checking. Ah well.. There's probably an easy way I haven't thought of yet. Do enlighten me.Agreed, it does get a bit confusing at times, but the phrase 'buf[0..4]' in this context is the address of a slice (dynamic array). So trying to cast a dynamic array to an integer is not going to work. Given that a dynamic array is equivalent to struct { void *data; uint length }; However, if you treat the slice as an address, you can play with that ... <code> import std.stdio; import std.stdint; void main() { char[] s = "abcdefghijiklmnopqrstuvwxyz"; uint32_t v; for(int i = 0; i <= s.length-v.sizeof; i++) { v = *(cast(uint32_t *)s[i .. i+v.sizeof]); writefln("%d 0x%08x %s ", v, v, s[i .. i+v.sizeof]); } } </code> -- Derek Melbourne, Australia 21/03/2005 10:59:44 AM
Mar 20 2005
"nod" <nod_member pathlink.com> wrote in message news:d1kn6g$19a3$1 digitaldaemon.com...Is there a good reason why the following should not be allowed: --- char[] buf; // ...read into buf... uint32_t fourcc = cast(uint32_t) buf[0..4]; --- The values are the same size, and the code clearly shows my intention to reinterpret the byte data as an integer value. I could cast to pointersandback, but that's kind of roundabout and then I lose automatic boundschecking.Ah well.. There's probably an easy way I haven't thought of yet. Doenlightenme.uint fourcc = *cast(uint *)buf.ptr;
Mar 20 2005