www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Not sure

reply Tom <Tom_member pathlink.com> writes:
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
Dec 14 2005
next sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
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
Dec 14 2005
parent reply Tom <Tom_member pathlink.com> writes:
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
Dec 14 2005
next sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
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
Dec 14 2005
parent reply James Dunne <james.jdunne gmail.com> writes:
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

Dec 14 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
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...

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
Dec 15 2005
parent reply James Dunne <james.jdunne gmail.com> writes:
Regan Heath wrote:
 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)

Oops on the dynamic array stuff.
 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 :)

Oops again. :)
 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)

No, the original code posted is not modifying the static array's effective pointer, but is instead attempting to copy the data out of a casted-to ubyte[4] static array. The cast is what is the invalid operation here.
 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

I believe the implementation of the slice call is defined in the phobos standard library as a regular C function call, so it is not up to the language to decide what to do here. The memory should be allocated dynamically on the heap, but it is definitely not required to be. This is another implementation detail.
Dec 15 2005
next sibling parent "Regan Heath" <regan netwin.co.nz> writes:
On Thu, 15 Dec 2005 13:56:13 -0600, James Dunne <james.jdunne gmail.com>  
wrote:
 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.

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)

No, the original code posted is not modifying the static array's effective pointer, but is instead attempting to copy the data out of a casted-to ubyte[4] static array. The cast is what is the invalid operation here.

You're missing my point. Answer me this; the cast is illegal because _______? You're correct, the original code was not modifying the pointer, my mistake. But, there must be some reason the cast is illegal. That reason appears to me to be that there is simply no such thing as a temporary static array, perhaps due to the nature/specification of them, perhaps due to the implementation of them, perhaps some other reason...
 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.

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.

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

I believe the implementation of the slice call is defined in the phobos standard library as a regular C function call, so it is not up to the language to decide what to do here. The memory should be allocated dynamically on the heap, but it is definitely not required to be. This is another implementation detail.

Sure, it's entirely possible a clever implementation can optimise the temporary away. Regardless it's important to understand what is going on figuratively if not actually, as the first usually leads to the other. Regan
Dec 15 2005
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
On Thu, 15 Dec 2005 13:56:13 -0600, James Dunne wrote:

BTW, the D Language docs in the ABI section clearly defines the dynamic
array implementation structure.

--------------
Arrays
A dynamic array consists of: 

offset 	contents 	
0 	array dimension 	
4 	pointer to array data 	

-------------------

So this code is 'legal' but still hackish.

   *(cast(int**)(cast(void*)&ub + int.sizeof)) = &i;


-- Derek Parnell Melbourne, Australia 16/12/2005 7:51:40 AM
Dec 15 2005
parent Tom <Tom_member pathlink.com> writes:
Again people :D, I appreciate the workarounds very much but as I said before,
this isn't real code excerpt but a pure abstract example. The only question I'm
asking here (and I wish someone can answer) is why is the cast wrong?, as Regan
(I think) understood from the very beginning. 

Thanks :)  
Tom

In article <ikigr00oc3am.1aykemsuvx5on.dlg 40tude.net>, Derek Parnell says...
On Thu, 15 Dec 2005 13:56:13 -0600, James Dunne wrote:

BTW, the D Language docs in the ABI section clearly defines the dynamic
array implementation structure.

--------------
Arrays
A dynamic array consists of: 

offset 	contents 	
0 	array dimension 	
4 	pointer to array data 	

-------------------

So this code is 'legal' but still hackish.

   *(cast(int**)(cast(void*)&ub + int.sizeof)) = &i;


-- Derek Parnell Melbourne, Australia 16/12/2005 7:51:40 AM

Dec 15 2005
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
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
Dec 14 2005
parent "Regan Heath" <regan netwin.co.nz> writes:
On Thu, 15 Dec 2005 18:13:54 +1100, Derek Parnell <derek psych.ward> wrote:
 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.

The alternative to copying is to use a dynamic array instead of a static one, i.e. ubyte[] ub; and to assign rather than copy the result, i.e. ub = (cast(ubyte*)&i)[0..4] Regan
Dec 15 2005
prev sibling next sibling parent reply Derek Parnell <derek psych.ward> writes:
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
Dec 14 2005
parent reply Bruno Medeiros <daiphoenixNO SPAMlycos.com> writes:
Derek Parnell wrote:
 On Thu, 15 Dec 2005 01:58:59 +0000 (UTC), Tom wrote:
 
    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;

Whoa, now that is strange. I've allways thought that the dynamic arrays's first element was the pointer, and the second the length. It just seem more natural that way, because.. well, it makes them more like pointers. For instance, you could do an opaque cast of dyn array to pointer (of the same type), and also the (generated assembly) code to index a dyn array would be the same as the pointer's. -- Bruno Medeiros - CS/E student "Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
Dec 16 2005
next sibling parent Tom <Tom_member pathlink.com> writes:
In article <dnv1p9$2gv0$1 digitaldaemon.com>, Bruno Medeiros says...
Derek Parnell wrote:
 On Thu, 15 Dec 2005 01:58:59 +0000 (UTC), Tom wrote:
 
    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;

Whoa, now that is strange. I've allways thought that the dynamic arrays's first element was the pointer, and the second the length. It just seem more natural that way, because.. well, it makes them more like pointers. [...]

I don't think it's more natural but I agree that casting would be straightforward if that was the case (don't have to add to the pointer). Was that you were referring about making it more like a pointer? I always thought it was implemented as prefixed length as in other languages strings are. Not sure :) Tom;
Dec 16 2005
prev sibling parent reply Sean Kelly <sean f4.ca> writes:
Bruno Medeiros wrote:
 Derek Parnell wrote:
 On Thu, 15 Dec 2005 01:58:59 +0000 (UTC), Tom wrote:

    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;

Whoa, now that is strange. I've allways thought that the dynamic arrays's first element was the pointer, and the second the length. It just seem more natural that way, because.. well, it makes them more like pointers. For instance, you could do an opaque cast of dyn array to pointer (of the same type), and also the (generated assembly) code to index a dyn array would be the same as the pointer's.

Switching them would break the ability to do this: char[] buf; printf( "%.*s", buf ); Also, it's typical for length information to precede the data--allocated memory blocks, for example. Sean
Dec 16 2005
parent reply Bruno Medeiros <daiphoenixNO SPAMlycos.com> writes:
Sean Kelly wrote:
 Bruno Medeiros wrote:
 
 Derek Parnell wrote:

 On Thu, 15 Dec 2005 01:58:59 +0000 (UTC), Tom wrote:

    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;

> Whoa, now that is strange. I've allways thought that the dynamic arrays's first element was the pointer, and the second the length. It just seem more natural that way, because.. well, it makes them more like pointers. For instance, you could do an opaque cast of dyn array to pointer (of the same type), and also the (generated assembly) code to index a dyn array would be the same as the pointer's.

Switching them would break the ability to do this: char[] buf; printf( "%.*s", buf );

char[] buf; printf( "%s", buf ); well, mostly... if it weren't for the zero-termination issue. In fact, since the moment that printf is made to work with zero-terminated strings, and D's strings are not zero-terminated, we probably shouldn't bother with any kind of (direct) compatibility. -- Bruno Medeiros - CS/E student "Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
Dec 17 2005
parent reply James Dunne <james.jdunne gmail.com> writes:
Bruno Medeiros wrote:
 Sean Kelly wrote:
 
 Bruno Medeiros wrote:

 Derek Parnell wrote:

 On Thu, 15 Dec 2005 01:58:59 +0000 (UTC), Tom wrote:

    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;

> Whoa, now that is strange. I've allways thought that the dynamic arrays's first element was the pointer, and the second the length. It just seem more natural that way, because.. well, it makes them more like pointers. For instance, you could do an opaque cast of dyn array to pointer (of the same type), and also the (generated assembly) code to index a dyn array would be the same as the pointer's.

Switching them would break the ability to do this: char[] buf; printf( "%.*s", buf );

char[] buf; printf( "%s", buf ); well, mostly... if it weren't for the zero-termination issue. In fact, since the moment that printf is made to work with zero-terminated strings, and D's strings are not zero-terminated, we probably shouldn't bother with any kind of (direct) compatibility.

Don't forget about UTF-8... Using writef is a better alternative anyway. I don't use it much myself since I use ASCII strings, and writef is much slower than printf.
Dec 18 2005
parent Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
James Dunne wrote:

 Don't forget about UTF-8...  Using writef is a better alternative 
 anyway.  I don't use it much myself since I use ASCII strings, and 
 writef is much slower than printf.

Except for throwing on bad code units/combinations, In what way does writef handle UTF-8 that printf doesn't? /Oskar
Dec 19 2005
prev sibling next sibling parent reply MicroWizard <MicroWizard_member pathlink.com> writes:
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

Dec 15 2005
parent Tom <Tom_member pathlink.com> writes:
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
Dec 15 2005
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
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]

Oops, I got side tracked ;-) Ok so here's an attempt at explaining the problem... The 'cast(ubyte[4])' is telling the compiler to treat the expression that follows as if it was a fixed-size array of 4 ubytes. What follows is '&i' which is the address of an int. So you are asking for the address of an int to be viewed as if it was a block of RAM which is 4 bytes long containing ubytes. But the evaluated expression '&i' is not stored in RAM so the compiler can't paint it with 'ubyte[4]'. -- 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 16/12/2005 2:19:42 PM
Dec 15 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Fri, 16 Dec 2005 14:25:34 +1100, Derek Parnell <derek psych.ward> wrote:
 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]

Oops, I got side tracked ;-) Ok so here's an attempt at explaining the problem... The 'cast(ubyte[4])' is telling the compiler to treat the expression that follows as if it was a fixed-size array of 4 ubytes. What follows is '&i' which is the address of an int. So you are asking for the address of an int to be viewed as if it was a block of RAM which is 4 bytes long containing ubytes. But the evaluated expression '&i' is not stored in RAM so the compiler can't paint it with 'ubyte[4]'.

I don't think "not stored in RAM" is the reason, consider: void main() { uint i; ubyte[4] ub; uint* p = &i; ub[] = cast(ubyte[4])p; //e2ir: cannot cast from uint* to ubyte[4] } Regan
Dec 15 2005
parent reply Derek Parnell <derek psych.ward> writes:
On Fri, 16 Dec 2005 16:37:34 +1300, Regan Heath wrote:

 On Fri, 16 Dec 2005 14:25:34 +1100, Derek Parnell <derek psych.ward> wrote:
 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]

Oops, I got side tracked ;-) Ok so here's an attempt at explaining the problem... The 'cast(ubyte[4])' is telling the compiler to treat the expression that follows as if it was a fixed-size array of 4 ubytes. What follows is '&i' which is the address of an int. So you are asking for the address of an int to be viewed as if it was a block of RAM which is 4 bytes long containing ubytes. But the evaluated expression '&i' is not stored in RAM so the compiler can't paint it with 'ubyte[4]'.

I don't think "not stored in RAM" is the reason, consider: void main() { uint i; ubyte[4] ub; uint* p = &i; ub[] = cast(ubyte[4])p; //e2ir: cannot cast from uint* to ubyte[4] } Regan

True ... I think D has made a big mistake in using a single keyword 'cast' to mean 'paint' in some circumstances and 'convert' in others. It is not clear to me when either usage of the keyword is assumed by the compiler. Also, I can't think of a way to override one meaning of 'cast' to mean the other. So it we really did want to paint 'p' in your example with 'ubyte[4]' how is it done? -- 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 16/12/2005 2:56:37 PM
Dec 15 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Fri, 16 Dec 2005 15:12:54 +1100, Derek Parnell <derek psych.ward> wrote:
 On Fri, 16 Dec 2005 16:37:34 +1300, Regan Heath wrote:

 On Fri, 16 Dec 2005 14:25:34 +1100, Derek Parnell <derek psych.ward>  
 wrote:
 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]

Oops, I got side tracked ;-) Ok so here's an attempt at explaining the problem... The 'cast(ubyte[4])' is telling the compiler to treat the expression that follows as if it was a fixed-size array of 4 ubytes. What follows is '&i' which is the address of an int. So you are asking for the address of an int to be viewed as if it was a block of RAM which is 4 bytes long containing ubytes. But the evaluated expression '&i' is not stored in RAM so the compiler can't paint it with 'ubyte[4]'.

I don't think "not stored in RAM" is the reason, consider: void main() { uint i; ubyte[4] ub; uint* p = &i; ub[] = cast(ubyte[4])p; //e2ir: cannot cast from uint* to ubyte[4] } Regan

True ... I think D has made a big mistake in using a single keyword 'cast' to mean 'paint' in some circumstances and 'convert' in others. It is not clear to me when either usage of the keyword is assumed by the compiler. Also, I can't think of a way to override one meaning of 'cast' to mean the other. So it we really did want to paint 'p' in your example with 'ubyte[4]' how is it done?

I'm not sure you can ever paint something as a static array because you can never assign the result to a static array, because a static array's data pointer is immutable (ignoring the evil hackery you posted) or so it appears to me, eg void main() { uint i; ubyte[4] ub; uint* p = &i; ub = cast(ubyte[4])p; //cannot change reference to static array 'ub' //cannot assign to static array ub } Regan
Dec 15 2005
parent reply Derek Parnell <derek psych.ward> writes:
On Fri, 16 Dec 2005 17:42:02 +1300, Regan Heath wrote:

 I'm not sure you can ever paint something as a static array because you  
 can never assign the result to a static array, because a static array's  
 data pointer is immutable (ignoring the evil hackery you posted) or so it  
 appears to me, eg

A fixed-size array (a.k.a static array) does not have a data pointer. It just sits on the stack as 'x' bytes long.
 void main() {
    uint i;
    ubyte[4] ub;

In this case, 'ub' takes up four bytes of stack space. It isn't a pointer to some other four bytes.
    uint* p = &i;
    ub = cast(ubyte[4])p; //cannot change reference to static array 'ub'
 //cannot assign to static array ub
 }
 

But anyways, I would only do this sort of thing using a union. ---------- import std.stdio; void main() { union iu { uint i; ubyte[i.sizeof] ub; }; iu c; c.i = 1; // access 'c' as a uint writefln("%s", c.ub); // but display 'c' as a ubyte[4] c.i = 22; writefln("%s", c.ub); c.i = 333; writefln("%s", c.ub); c.i = 4444; writefln("%s", c.ub); } ----------- -- 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 16/12/2005 4:11:16 PM
Dec 15 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Fri, 16 Dec 2005 16:17:32 +1100, Derek Parnell <derek psych.ward> wrote:
 On Fri, 16 Dec 2005 17:42:02 +1300, Regan Heath wrote:

 I'm not sure you can ever paint something as a static array because you
 can never assign the result to a static array, because a static array's
 data pointer is immutable (ignoring the evil hackery you posted) or so  
 it
 appears to me, eg

A fixed-size array (a.k.a static array) does not have a data pointer. It just sits on the stack as 'x' bytes long.

I realise that. A fixed sized array _is_ just a data pointer and that pointer cannot be re-assigned, that was my point.. er ;) But, is this defined in the spec or is this an implementation detail (as James mentions) Regan
Dec 15 2005
parent reply Derek Parnell <derek psych.ward> writes:
On Fri, 16 Dec 2005 19:00:42 +1300, Regan Heath wrote:

 On Fri, 16 Dec 2005 16:17:32 +1100, Derek Parnell <derek psych.ward> wrote:
 On Fri, 16 Dec 2005 17:42:02 +1300, Regan Heath wrote:

 I'm not sure you can ever paint something as a static array because you
 can never assign the result to a static array, because a static array's
 data pointer is immutable (ignoring the evil hackery you posted) or so  
 it
 appears to me, eg

A fixed-size array (a.k.a static array) does not have a data pointer. It just sits on the stack as 'x' bytes long.

I realise that. A fixed sized array _is_ just a data pointer and that pointer cannot be re-assigned, that was my point.. er ;)

Sorry about this, but my point is that a fixed size array _is_not_ a data pointer. It *is* the data itself, and not a pointer to the data.
 But, is this defined in the spec or is this an implementation detail (as  
 James mentions)

The docs say "a static array always has the dimension statically available as part of the type, and so it is implemented like in C." and from that I read that the length is 'hard coded' in the expressions that refer to the array. Consider this program ... -------------------------- import std.stdio; class Foo { char[9] i; } void main() { union iu { char[9] i; ubyte[i.sizeof] ubi; Foo c; ubyte[c.sizeof] ubc; }; iu c; c.i[0..5] = "abcde"; // update the first 5 slots. writefln("%s", c.ubi); c.c = new Foo; writefln("%s", c.ubc); } =========== Its output is [97,98,99,100,101,255,255,255,255] [224,15,135,0] which is nine bytes. If 'i' was a data pointer it would only be four bytes long. However, 'c' is a pointer and only its four bytes are shown. -- 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 16/12/2005 6:00:59 PM
Dec 15 2005
next sibling parent Bruno Medeiros <daiphoenixNO SPAMlycos.com> writes:
Derek Parnell wrote:
I realise that. A fixed sized array _is_ just a data pointer and that  
pointer cannot be re-assigned, that was my point.. er ;)

Sorry about this, but my point is that a fixed size array _is_not_ a data pointer. It *is* the data itself, and not a pointer to the data.
But, is this defined in the spec or is this an implementation detail (as  
James mentions)

The docs say "a static array always has the dimension statically available as part of the type, and so it is implemented like in C." and from that I read that the length is 'hard coded' in the expressions that refer to the array.

I think you are both /sorta/ wrong. I have just realized that a static array is in fact *exactly* a const dynamic array. It has exactly the same properties (like .ptr and .length) as a dyn array, only they're const (as in compile-time constant). They do not exist at runtime, except as inlined in code instructions. In fact, nothing of what you said or were thinking was actually wrong (thus the /sorta/), they are just differente but equivalent mental models(so to say), of the same thing. However, this mental model that I just presented is (I think) a more "correct" one. It allows us, for instance, to realize that: char[4] = "1234"; is *exactly* the same as: const char[] = "1234"; It also allows us to explain more clearly why: ub[] = cast(ubyte[4]) p; isn't allowed. Namely, the expression (cast(ubyte[4]) p) doesn't work because the resulting expression would have to be a const dyn array (or let's just call it const array, array being the struct with .ptr and .length ). As such, the resulting .ptr and .length would have to known at compile time. The .length is known, it is 4, as specified by the cast, however, the .ptr would be = p , but since p is not a const value, it doesn't work. Also, as a corolary, it theoretically could work if p was const too. -- Bruno Medeiros - CS/E student "Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
Dec 16 2005
prev sibling parent Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
Derek Parnell wrote:
 On Fri, 16 Dec 2005 19:00:42 +1300, Regan Heath wrote:
 
 
On Fri, 16 Dec 2005 16:17:32 +1100, Derek Parnell <derek psych.ward> wrote:

On Fri, 16 Dec 2005 17:42:02 +1300, Regan Heath wrote:


I'm not sure you can ever paint something as a static array because you
can never assign the result to a static array, because a static array's
data pointer is immutable (ignoring the evil hackery you posted) or so  
it
appears to me, eg

A fixed-size array (a.k.a static array) does not have a data pointer. It just sits on the stack as 'x' bytes long.

I realise that. A fixed sized array _is_ just a data pointer and that pointer cannot be re-assigned, that was my point.. er ;)

Sorry about this, but my point is that a fixed size array _is_not_ a data pointer. It *is* the data itself, and not a pointer to the data.

Upon declaration, a static array defines the storage of its contents, but when used as a type, it behaves as a pointer to the data. This is the same behaviour as in C. Consider: void func(char[5] arg) { arg[1] = 'x'; } void main() { char[5] test = "abcd"; func(test); printf(test ~ \n); } Will print "axcd". The contents is not copied when calling the function, the pointer is all that gets passed on. While, as you say, for struct Test { char[5] test; } Test.sizeof will be 5. This behaviour is (as far as I know) unfortunately not replicable in user defined types. I.e. if MyCharArray!(5) made struct Test { MyCharArray!(5) test; } have a size of 5, this function void func(MyCharArray!(5) arg) { ... } would pass the arg by value.
Dec 19 2005