Thread overview
reinterpret_cast or something...
Mar 20, 2005
nod
Mar 20, 2005
Ben Hinkle
Mar 20, 2005
nod
Mar 20, 2005
Ben Hinkle
Mar 20, 2005
Lukas Pinkowski
Mar 21, 2005
nod
Mar 21, 2005
xs0
Mar 21, 2005
Derek Parnell
Mar 21, 2005
Walter
March 20, 2005
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.


March 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


March 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;
>
>-Ben
>
>
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;
}
---

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?


March 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...
>>
>>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.

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)


March 20, 2005
nod wrote:
>>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.

You're dereferencing the wrong pointer, it should be

uint fourcc = *(cast(uint*) buf[0..4].ptr);

> ---
> 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;
> }

March 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
March 21, 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.

uint fourcc = *cast(uint *)buf.ptr;



March 21, 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!


March 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!
> 
>