Jump to page: 1 2 3
Thread overview
Not sure
Dec 15, 2005
Tom
Dec 15, 2005
Regan Heath
Dec 15, 2005
Tom
Dec 15, 2005
Regan Heath
Dec 15, 2005
James Dunne
Dec 15, 2005
Regan Heath
Dec 15, 2005
James Dunne
Dec 15, 2005
Regan Heath
Dec 15, 2005
Derek Parnell
Dec 16, 2005
Tom
Dec 15, 2005
Derek Parnell
Dec 15, 2005
Regan Heath
Dec 15, 2005
Derek Parnell
Dynamic Array ABI: Whoa.. ?
Dec 16, 2005
Bruno Medeiros
Dec 16, 2005
Tom
Dec 16, 2005
Sean Kelly
Dec 17, 2005
Bruno Medeiros
Dec 18, 2005
James Dunne
Dec 19, 2005
Oskar Linde
Dec 15, 2005
MicroWizard
Dec 15, 2005
Tom
Dec 16, 2005
Derek Parnell
Dec 16, 2005
Regan Heath
Dec 16, 2005
Derek Parnell
Dec 16, 2005
Regan Heath
Dec 16, 2005
Derek Parnell
Dec 16, 2005
Regan Heath
Dec 16, 2005
Derek Parnell
Dynamic Arrays and Static Arrays
Dec 16, 2005
Bruno Medeiros
Dec 19, 2005
Oskar Linde
December 15, 2005
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
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
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
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
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
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
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
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
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
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
« First   ‹ Prev
1 2 3