Thread overview
How to do "cast(ubyte[4])some_uint" in D1?
Jun 02, 2011
Nick Sabalausky
Jun 02, 2011
bearophile
Jun 02, 2011
Timon Gehr
Jun 02, 2011
Nick Sabalausky
Jun 02, 2011
Nick Sabalausky
June 02, 2011
In D2, I can treat a uint as an array of ubytes by doing this:

uint num = /+...whatever...+/;
ubyte[] = cast(ubyte[4])num;

How do I do that in D1?

IIRC, D1 requires an explicit slice operator to convert from a static-array to a slice/dynamic-array, so I tried this:

ubyte[] = (cast(ubyte[4])num)[];

But I get the error:
Error: e2ir: cannot cast num of type uint to type ubyte[4u]


June 02, 2011
Nick Sabalausky:

> In D2, I can treat a uint as an array of ubytes by doing this:
> 
> uint num = /+...whatever...+/;
> ubyte[] = cast(ubyte[4])num;
> 
> How do I do that in D1?

Using a union is probably the safest way:

union Uint2Ubyte {
    uint u;
    ubyte[4] b;
}

By the way, this of type conversions is a shady area in D.

Bye,
bearophile
June 02, 2011
> Nick Sabalausky:
>
>> In D2, I can treat a uint as an array of ubytes by doing this:
>>
>> uint num = /+...whatever...+/;
>> ubyte[] = cast(ubyte[4])num;
>>
>> How do I do that in D1?
>
> Using a union is probably the safest way:
>
> union Uint2Ubyte {
>     uint u;
>     ubyte[4] b;
> }
>
> By the way, this of type conversions is a shady area in D.
>
> Bye,
> bearophile

I think it is no so shady after all:
I tested the following code in DMD 2.053:
void main(){
    uint a;
    ubyte[] b = cast(ubyte[4])a;
}

It gives the same error as in D1.

Timon
June 02, 2011
On Thu, 02 Jun 2011 05:35:40 -0400, Nick Sabalausky <a@a.a> wrote:

> In D2, I can treat a uint as an array of ubytes by doing this:
>
> uint num = /+...whatever...+/;
> ubyte[] = cast(ubyte[4])num;
>
> How do I do that in D1?
>
> IIRC, D1 requires an explicit slice operator to convert from a static-array
> to a slice/dynamic-array, so I tried this:
>
> ubyte[] = (cast(ubyte[4])num)[];
>
> But I get the error:
> Error: e2ir: cannot cast num of type uint to type ubyte[4u]

We can learn from C here :)

ubyte[] x = (cast(ubyte *)&num)[0..4];

Essentially, pointers are *always* castable to one another, and do not go through any translations.  Go to pointer-land, then back, and all your casts shall work.  It's how C++'s reinterpret_cast works.

-Steve
June 02, 2011
"Timon Gehr" <timon.gehr@gmx.ch> wrote in message news:is7ojo$2ggv$1@digitalmars.com...
>> Nick Sabalausky:
>>
>>> In D2, I can treat a uint as an array of ubytes by doing this:
>>>
>>> uint num = /+...whatever...+/;
>>> ubyte[] = cast(ubyte[4])num;
>>>
>>> How do I do that in D1?
>>
>> Using a union is probably the safest way:
>>
>> union Uint2Ubyte {
>>     uint u;
>>     ubyte[4] b;
>> }
>>
>> By the way, this of type conversions is a shady area in D.
>>
>> Bye,
>> bearophile
>
> I think it is no so shady after all:
> I tested the following code in DMD 2.053:
> void main(){
>    uint a;
>    ubyte[] b = cast(ubyte[4])a;
> }
>
> It gives the same error as in D1.
>

Ok, that's just bizarre. I've just check and verified that you're right. But I could swear I've done that sort of thing before, and without using the pointer trick Steve pointed out...



June 02, 2011
"Nick Sabalausky" <a@a.a> wrote in message news:is8qu8$1cq3$1@digitalmars.com...
> "Timon Gehr" <timon.gehr@gmx.ch> wrote in message news:is7ojo$2ggv$1@digitalmars.com...
>>> Nick Sabalausky:
>>>
>>>> In D2, I can treat a uint as an array of ubytes by doing this:
>>>>
>>>> uint num = /+...whatever...+/;
>>>> ubyte[] = cast(ubyte[4])num;
>>>>
>>>> How do I do that in D1?
>>>
>>> Using a union is probably the safest way:
>>>
>>> union Uint2Ubyte {
>>>     uint u;
>>>     ubyte[4] b;
>>> }
>>>
>>> By the way, this of type conversions is a shady area in D.
>>>
>>> Bye,
>>> bearophile
>>
>> I think it is no so shady after all:
>> I tested the following code in DMD 2.053:
>> void main(){
>>    uint a;
>>    ubyte[] b = cast(ubyte[4])a;
>> }
>>
>> It gives the same error as in D1.
>>
>
> Ok, that's just bizarre. I've just check and verified that you're right. But I could swear I've done that sort of thing before, and without using the pointer trick Steve pointed out...
>

Ah ha! I figured out what I had done before. In D2, casting a struct to a same-sized static array works fine:

struct Foo {uint f;}
void main(){
    Foo a;
    ubyte[] b = cast(ubyte[4])a;
}

Verified on DMD 2.053, 2.052 and 2.051. It doesn't work on D1 though (at least not 1.066 with tango trunk). But I'll try Steve's pointer trick for that.

As a nice touch, it fails in D2 if you change the "ubyte[4]" to "ubyte[5]". Using "ubyte[3]" is prohibited, too, even though I would think that should be ok. But that's probably not a real big deal.

But...it seems strange that casting a primitive to a static array would be prohibited if it's perfectly kosher when the primitive is in a struct. So I've filed a bug report on that:

Can't cast primitive to same-sized static array http://d.puremagic.com/issues/show_bug.cgi?id=6092