Thread overview | ||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
December 15, 2005 Not sure | ||||
---|---|---|---|---|
| ||||
I'm not sure if someone post this before (maybe this is just a copy-paste, I don't recall as I have the d file missed in some directory and I've just found it), but I'm wondering isn't this cast possible? # int main( char[][] args ) # { # int i; # ubyte[4] ub; # ub[] = cast(ubyte[4]) &i; # return 0; # } test.d(5): cannot cast int* to ubyte[4] DMD 0.141 Tom |
December 15, 2005 Re: Not sure | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tom | On Thu, 15 Dec 2005 01:58:59 +0000 (UTC), Tom <Tom_member@pathlink.com> wrote:
> I'm not sure if someone post this before (maybe this is just a copy-paste, I
> don't recall as I have the d file missed in some directory and I've just found
> it), but I'm wondering isn't this cast possible?
>
> # int main( char[][] args )
> # {
> # int i;
> # ubyte[4] ub;
> # ub[] = cast(ubyte[4]) &i;
> # return 0;
> # }
>
> test.d(5): cannot cast int* to ubyte[4]
> DMD 0.141
Try:
# int main( char[][] args )
# {
# int i;
# ubyte[4] ub;
# ub[] = (cast(ubyte*)&i)[0..4];
# return 0;
# }
Regan
|
December 15, 2005 Re: Not sure | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | In article <ops1sym6qr23k2f5@nrage.netwin.co.nz>, Regan Heath says... > >On Thu, 15 Dec 2005 01:58:59 +0000 (UTC), Tom <Tom_member@pathlink.com> wrote: >> I'm not sure if someone post this before (maybe this is just a >> copy-paste, I >> don't recall as I have the d file missed in some directory and I've just >> found >> it), but I'm wondering isn't this cast possible? >> >> # int main( char[][] args ) >> # { >> # int i; >> # ubyte[4] ub; >> # ub[] = cast(ubyte[4]) &i; >> # return 0; >> # } >> >> test.d(5): cannot cast int* to ubyte[4] >> DMD 0.141 > >Try: ># int main( char[][] args ) ># { ># int i; ># ubyte[4] ub; ># ub[] = (cast(ubyte*)&i)[0..4]; ># return 0; ># } > >Regan Yap, this works fine but, why is the former bad? Tom |
December 15, 2005 Re: Not sure | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tom | On Thu, 15 Dec 2005 02:33:02 +0000 (UTC), Tom <Tom_member@pathlink.com> wrote:
> In article <ops1sym6qr23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>
>> On Thu, 15 Dec 2005 01:58:59 +0000 (UTC), Tom <Tom_member@pathlink.com>
>> wrote:
>>> I'm not sure if someone post this before (maybe this is just a
>>> copy-paste, I
>>> don't recall as I have the d file missed in some directory and I've just
>>> found
>>> it), but I'm wondering isn't this cast possible?
>>>
>>> # int main( char[][] args )
>>> # {
>>> # int i;
>>> # ubyte[4] ub;
>>> # ub[] = cast(ubyte[4]) &i;
>>> # return 0;
>>> # }
>>>
>>> test.d(5): cannot cast int* to ubyte[4]
>>> DMD 0.141
>>
>> Try:
>> # int main( char[][] args )
>> # {
>> # int i;
>> # ubyte[4] ub;
>> # ub[] = (cast(ubyte*)&i)[0..4];
>> # return 0;
>> # }
>>
>> Regan
>
> Yap, this works fine but, why is the former bad?
Tough question :)
ubyte[4] is a static array. I believe D implements it as a pointer to a block of memory, and does macro style replacement of "ub.length" with "4".
&i is an int*, a pointer to a block of memory containing an 'int' (supposedly).
Both blocks of memory are 4 bytes long. So, apart from one technically supposedly being an "int" and the other technically being "4 bytes in a row" they're the same thing.
However, I do not think it's possible to make a static array point to another address, so this may be why it fails.
My code works because you can slice a pointer/memory address to create a dynamic array of the type of the pointer. The statement:
(cast(ubyte*)&i)[0..4];
creates a temporary dynamic array, which is then copied into the memory block pointed to by ub, the static array.
Regan
|
December 15, 2005 Re: Not sure | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | Regan Heath wrote: > On Thu, 15 Dec 2005 02:33:02 +0000 (UTC), Tom <Tom_member@pathlink.com> wrote: > >> In article <ops1sym6qr23k2f5@nrage.netwin.co.nz>, Regan Heath says... >> >>> >>> On Thu, 15 Dec 2005 01:58:59 +0000 (UTC), Tom <Tom_member@pathlink.com> >>> wrote: >>> >>>> I'm not sure if someone post this before (maybe this is just a >>>> copy-paste, I >>>> don't recall as I have the d file missed in some directory and I've just >>>> found >>>> it), but I'm wondering isn't this cast possible? >>>> >>>> # int main( char[][] args ) >>>> # { >>>> # int i; >>>> # ubyte[4] ub; >>>> # ub[] = cast(ubyte[4]) &i; >>>> # return 0; >>>> # } >>>> >>>> test.d(5): cannot cast int* to ubyte[4] >>>> DMD 0.141 >>> >>> >>> Try: >>> # int main( char[][] args ) >>> # { >>> # int i; >>> # ubyte[4] ub; >>> # ub[] = (cast(ubyte*)&i)[0..4]; >>> # return 0; >>> # } >>> >>> Regan >> >> >> Yap, this works fine but, why is the former bad? > > > Tough question :) > > ubyte[4] is a static array. I believe D implements it as a pointer to a block of memory, and does macro style replacement of "ub.length" with "4". > > &i is an int*, a pointer to a block of memory containing an 'int' (supposedly). > > Both blocks of memory are 4 bytes long. So, apart from one technically supposedly being an "int" and the other technically being "4 bytes in a row" they're the same thing. > No, it's a bad idea for the D language spec to assume any implementation-specific details. In this case, the implementation of a dynamic array. At no point in the D language spec regarding dynamic arrays is any ordering of the fields in the implicit memory structure of a dynamic array stated. In fact, Walter points out that relying on such implementation-specific details to get printf working is a bad idea: "In the future, it may be necessary to just add a new format specifier to printf() instead of relying on an implementation dependent detail." (from http://digitalmars.com/d/arrays.html under 'printf() and Strings' section). What he is referring to is that strings are special-case dynamic arrays. The printf '%.*s' format specifier expects a length integer followed by a data pointer. It just so happens to be (most likely by design) that the reference DMD compiler orders the dynamic array's fields in memory as length first, followed by data pointer. Thus, your argument shouldn't hold in general because you're assuming the D language defines the ordering of the dynamic array's members. > However, I do not think it's possible to make a static array point to another address, so this may be why it fails. > No, the compiler states quite clearly that the cast from an int* to a ubyte[4] is simply not allowed. I'm not disagreeing that you cannot modify the address a static array points to, I'm just disagreeing with your proposed reason for the 'failure' case. I believe for a cast from a pointer to an array to succeed, both element types must be exactly equivalent, not just source pointer-element type castable to destination array-element type. > My code works because you can slice a pointer/memory address to create a dynamic array of the type of the pointer. The statement: > > (cast(ubyte*)&i)[0..4]; > > creates a temporary dynamic array, which is then copied into the memory block pointed to by ub, the static array. > I don't believe this creates any memory. Slices are references to the original data. What effectively is being done here is copying 4 ubytes from the address of a local int variable into the ub[] static array. If one does not want the value copied, then simply use a union on int and ubyte[4]. > Regan |
December 15, 2005 Re: Not sure | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tom | On Thu, 15 Dec 2005 01:58:59 +0000 (UTC), Tom wrote: > I'm not sure if someone post this before (maybe this is just a copy-paste, I don't recall as I have the d file missed in some directory and I've just found it), but I'm wondering isn't this cast possible? > > # int main( char[][] args ) > # { > # int i; > # ubyte[4] ub; > # ub[] = cast(ubyte[4]) &i; > # return 0; > # } > > test.d(5): cannot cast int* to ubyte[4] I'm not sure what you are attempting to do. But if you are trying to have 'ub' reference the integer 'i' as if it was four bytes then this might do the trick (btw: its a hack 'cos it assumes D's dynamic array ABI is not going to change). ----------------- import std.stdio; int main( char[][] args ) { int i; ubyte[] ub; // Set the length first! ub.length = i.sizeof; // Pretend that the 2nd part of ub (the pointer part) is // a pointer to a integer rather than the RAM that // was allocated by setting the length. Set this part // to point to the integer in question. *(cast(int**)(cast(void*)&ub + int.sizeof)) = &i; i = 11; writefln("i = %d", i); writefln("ub = %s", ub); i = 222; writefln("i = %d", i); writefln("ub = %s", ub); i = 3333; writefln("i = %d", i); writefln("ub = %s", ub); return 0; } --------------------- OUTPUT::::: i = 11 ub = [11,0,0,0] i = 222 ub = [222,0,0,0] i = 3333 ub = [5,13,0,0] Personally, I'd use a union instead ;-) -- Derek (skype: derek.j.parnell) Melbourne, Australia "A learning experience is one of those things that says, 'You know that thing you just did? Don't do that.'" - D.N. Adams 15/12/2005 6:05:15 PM |
December 15, 2005 Re: Not sure | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tom | On Thu, 15 Dec 2005 02:33:02 +0000 (UTC), Tom wrote: >># ub[] = (cast(ubyte*)&i)[0..4]; Oh... you just wanted to copy the integer to the ub array. Okay. -- Derek (skype: derek.j.parnell) Melbourne, Australia "A learning experience is one of those things that says, 'You know that thing you just did? Don't do that.'" - D.N. Adams 15/12/2005 6:13:01 PM |
December 15, 2005 Re: Not sure | ||||
---|---|---|---|---|
| ||||
Posted in reply to James Dunne | On Thu, 15 Dec 2005 00:31:18 -0600, James Dunne <james.jdunne@gmail.com> wrote: > Regan Heath wrote: >> On Thu, 15 Dec 2005 02:33:02 +0000 (UTC), Tom <Tom_member@pathlink.com> wrote: >> >>> In article <ops1sym6qr23k2f5@nrage.netwin.co.nz>, Regan Heath says... >> Both blocks of memory are 4 bytes long. So, apart from one technically supposedly being an "int" and the other technically being "4 bytes in a row" they're the same thing. >> > > No, it's a bad idea for the D language spec to assume any implementation-specific details. In this case, the implementation of a dynamic array. ub is not a dynamic array it is a static array. That said (I believe) you point is still valid because I can't recall reading anything defining the static array implementation either (what I know of it is based on observation and guess work) > At no point in the D language spec regarding dynamic arrays is any ordering of the fields in the implicit memory structure of a dynamic array stated. In fact, Walter points out that relying on such implementation-specific details to get printf working is a bad idea: "In the future, it may be necessary to just add a new format specifier to printf() instead of relying on an implementation dependent detail." (from http://digitalmars.com/d/arrays.html under 'printf() and Strings' section). > > What he is referring to is that strings are special-case dynamic arrays. The printf '%.*s' format specifier expects a length integer followed by a data pointer. It just so happens to be (most likely by design) that the reference DMD compiler orders the dynamic array's fields in memory as length first, followed by data pointer. > > Thus, your argument shouldn't hold in general because you're assuming the D language defines the ordering of the dynamic array's members. You make a valid point, for dynamic arrays.. but we're not talking about dynamic arrays :) >> However, I do not think it's possible to make a static array point to another address, so this may be why it fails. >> > > No, the compiler states quite clearly that the cast from an int* to a ubyte[4] is simply not allowed. I'm not disagreeing that you cannot modify the address a static array points to, I'm just disagreeing with your proposed reason for the 'failure' case. There must be some reason the compiler is disallowing it, it's not doing so just out of spite, right? As to what that reason is.. my best guess remains that a static array pointer is immutable. (which happens to be the implementation that was chosen by DMD, and is undefined in the spec to my knowledge) > I believe for a cast from a pointer to an array to succeed, both element types must be exactly equivalent, not just source pointer-element type castable to destination array-element type. AFAIK you can't actually cast from a pointer to an array. Unless you count what Derek posted: *(cast(int**)(cast(void*)&ub + int.sizeof)) = &i; You can however slice a pointer which creates a dynamic array, that's what happens here: (cast(ubyte*)&i)[0..4]; >> My code works because you can slice a pointer/memory address to create a dynamic array of the type of the pointer. The statement: >> (cast(ubyte*)&i)[0..4]; >> creates a temporary dynamic array, which is then copied into the memory block pointed to by ub, the static array. >> > > I don't believe this creates any memory. Slices are references to the original data. What effectively is being done here is copying 4 ubytes from the address of a local int variable into the ub[] static array. Correct, except when you slice a pointer you get a dynamic array, a dynamic array consists of a pointer and a length, or 8 bytes of data, so, unless the compiler optimises this away this statement: ub[] = (cast(ubyte*)&i)[0..4]; uses 8 bytes of temporary memory on the stack (or is it on the heap?) Regan |
December 15, 2005 Re: Not sure | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tom | I think you just wanted to convert a 32 bit int to it's binary representative. However the mentioned cast should be work somehow, you have to use union for this problem keeping in mind that the result depends on the underlying architecture eg. big or little endianness. On the other hand 'int' is 32 bit now but it is not guaranteed. Tamás Nagy In article <dnqil3$26k5$1@digitaldaemon.com>, Tom says... > >I'm not sure if someone post this before (maybe this is just a copy-paste, I don't recall as I have the d file missed in some directory and I've just found it), but I'm wondering isn't this cast possible? > ># int main( char[][] args ) ># { ># int i; ># ubyte[4] ub; ># ub[] = cast(ubyte[4]) &i; ># return 0; ># } > >test.d(5): cannot cast int* to ubyte[4] >DMD 0.141 > >Tom |
December 15, 2005 Re: Not sure | ||||
---|---|---|---|---|
| ||||
Posted in reply to MicroWizard | In article <dnrsb9$1l7$1@digitaldaemon.com>, MicroWizard says... > >I think you just wanted to convert a 32 bit int to it's binary >representative. However the mentioned cast should be work somehow, >you have to use union for this problem keeping in mind that >the result depends on the underlying architecture eg. big or little >endianness. On the other hand 'int' is 32 bit now but it is not guaranteed. Oh, yes, int = 32bits it's guaranteed as D defines so in it's specs. With respect to the union alternative, yes I would use a union but this isn't taken from real code, so is just an abstract example to illustrate the issue. >In article <dnqil3$26k5$1@digitaldaemon.com>, Tom says... >> >>I'm not sure if someone post this before (maybe this is just a copy-paste, I don't recall as I have the d file missed in some directory and I've just found it), but I'm wondering isn't this cast possible? >> >># int main( char[][] args ) >># { >># int i; >># ubyte[4] ub; >># ub[] = cast(ubyte[4]) &i; >># return 0; >># } >> >>test.d(5): cannot cast int* to ubyte[4] >>DMD 0.141 >> >>Tom > > Tom |
Copyright © 1999-2021 by the D Language Foundation