www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Array access via pointer

reply Robert <robert.muench robertmuench.de> writes:
Hi, I hope some of you D gurus can help me getting my mind setup 
correct when using D arrays.

I have an array: data[1 .. 2048] of type ubyte

I'm interested in getting the addresse of the array and its data 
members. So I used:

writefln("adress data[%d] = %d", 0, &data);
writefln("adress data[%d] = %d", 2047, &data[2047]);


And got:

address data[0] = 18FE50
address data[2047] = 2607FF

Which is:

 0x2607ff - 0x18fe50

ans = 854447 Shouldn't these addresses have a difference of 2047 bytes? Why do I get those strange addresses back? -- Robert M. Münch http://www.robertmuench.de
May 30 2010
next sibling parent reply Moritz Warning <moritzwarning web.de> writes:
On Sun, 30 May 2010 21:43:16 +0200, Robert wrote:

 Hi, I hope some of you D gurus can help me getting my mind setup correct
 when using D arrays.
 
 I have an array: data[1 .. 2048] of type ubyte
 
 I'm interested in getting the addresse of the array and its data
 members. So I used:
 
 writefln("adress data[%d] = %d", 0, &data);

try data.ptr instead of &data. Think of a dynamic array as a struct of a length value (.length) and a pointer (.ptr).
May 30 2010
next sibling parent Robert <robert.muench robertmuench.de> writes:
On 2010-05-30 21:50:10 +0200, Moritz Warning <moritzwarning web.de> said:

 try data.ptr instead of &data.

Ah, I was looking for something like this but didn't find it. Do all variables and types support the .ptr property? -- Robert M. Münch http://www.robertmuench.de
May 30 2010
prev sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Robert <robert.muench robertmuench.de> wrote:

 Ah, I was looking for something like this but didn't find it.

 Do all variables and types support the .ptr property?

Nope. Arrays do, as they are simply C arrays (T*) with a length attached, and some fancy goings-on behind the scenes. Basically, in C, the equivalent would be typedef struct array { int* ptr; int length; }; If I wanted something other than an array, such a structure makes little sense. Especially seeing as most anything other than a dynamic array could be stack-allocated, and we don't want any pointers to stack stuff to escape for long. -- Simen
May 30 2010
prev sibling parent reply Pelle <pelle.mansson gmail.com> writes:
On 05/30/2010 09:43 PM, Robert wrote:
 Hi, I hope some of you D gurus can help me getting my mind setup correct
 when using D arrays.

 I have an array: data[1 .. 2048] of type ubyte

 I'm interested in getting the addresse of the array and its data
 members. So I used:

 writefln("adress data[%d] = %d", 0, &data);
 writefln("adress data[%d] = %d", 2047, &data[2047]);


 And got:

 address data[0] = 18FE50
 address data[2047] = 2607FF

 Which is:

 0x2607ff - 0x18fe50

ans = 854447 Shouldn't these addresses have a difference of 2047 bytes? Why do I get those strange addresses back?

&data[0] and &data are very different things, if you have a dynamic array.
May 30 2010
next sibling parent reply Robert <robert.muench robertmuench.de> writes:
On 2010-05-30 22:16:55 +0200, Pelle <pelle.mansson gmail.com> said:

 &data[0] and &data are very different things, if you have a dynamic array.

Yes, that's what I found out too. What's the exact difference? -- Robert M. Münch http://www.robertmuench.de
May 30 2010
next sibling parent Pelle <pelle.mansson gmail.com> writes:
On 05/30/2010 11:00 PM, Robert wrote:
 On 2010-05-30 22:16:55 +0200, Pelle <pelle.mansson gmail.com> said:

 &data[0] and &data are very different things, if you have a dynamic
 array.

Yes, that's what I found out too. What's the exact difference?

A dynamic array is a fat pointer with a length, approximately a struct with a pointer and a size_t. &data is the address of this structure, of type ubyte[]*, whereas &data[0], or data.ptr is a pointer to the first element, of type ubyte*. I hope this clarifies things :)
May 30 2010
prev sibling parent reply Robert <robert.muench robertmuench.de> writes:
On 2010-05-30 23:12:06 +0200, "Simen kjaeraas" <simen.kjaras gmail.com> said:

 Going again with the C code:
 
 typedef struct array {
    int* data;
    int length;
 };
 
 You would use an array like this:
 
 void foo( ) {
     array arr;
     arr.ptr = malloc(32);
     arr.length = 8;
 }
 
 Now, as you can probbly see, &arr would give the pointer to the
 struct, not to the data. Basically, a pointer to pointer to int,
 rather than the pointer to int you want.

Ok, I thought that the structure was a bit more flat like: typedef struct array { int length; int[1..length] data; } Avoiding one indirection as it could be assumed that the memory-allocator / GC will return a continous piece for the array. But of course resizing and reallocation would be a bit more complicated. -- Robert M. Münch http://www.robertmuench.de
May 30 2010
next sibling parent BCS <none anon.com> writes:
Hello robert,

 But
 of course resizing and reallocation would be a bit more complicated.

and it would make slicing impossible: int[] a, b; a.length = 10; a[5] = 1; b = a[5..10]; assert(b[0] == 1); b[0] = 5; assert(a[5] == 5);
 

... <IXOYE><
May 30 2010
prev sibling parent Pelle <pelle.mansson gmail.com> writes:
On 05/30/2010 11:54 PM, Robert wrote:
 On 2010-05-30 23:12:06 +0200, "Simen kjaeraas" <simen.kjaras gmail.com>
 said:

 Going again with the C code:

 typedef struct array {
 int* data;
 int length;
 };

 You would use an array like this:

 void foo( ) {
 array arr;
 arr.ptr = malloc(32);
 arr.length = 8;
 }

 Now, as you can probbly see, &arr would give the pointer to the
 struct, not to the data. Basically, a pointer to pointer to int,
 rather than the pointer to int you want.

Ok, I thought that the structure was a bit more flat like: typedef struct array { int length; int[1..length] data; } Avoiding one indirection as it could be assumed that the memory-allocator / GC will return a continous piece for the array. But of course resizing and reallocation would be a bit more complicated.

Not avoiding an indirection if it's still located on the heap. I mean, pointer to (length and array), or (pointer and length) to array. Still just one level of indirection. The fat pointer solution also allow for arbitrary slicing.
May 30 2010
prev sibling next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Robert <robert.muench robertmuench.de> wrote:

 On 2010-05-30 22:16:55 +0200, Pelle <pelle.mansson gmail.com> said:

 &data[0] and &data are very different things, if you have a dynamic  
 array.

Yes, that's what I found out too. What's the exact difference?

Going again with the C code: typedef struct array { int* data; int length; }; You would use an array like this: void foo( ) { array arr; arr.ptr = malloc(32); arr.length = 8; } Now, as you can probbly see, &arr would give the pointer to the struct, not to the data. Basically, a pointer to pointer to int, rather than the pointer to int you want. -- Simen
May 30 2010
prev sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Robert <robert.muench robertmuench.de> wrote:

 Ok, I thought that the structure was a bit more flat like:

 typedef struct array {
 	int length;
 	int[1..length] data;
 }

 Avoiding one indirection as it could be assumed that the  
 memory-allocator / GC will return a continous piece for the array. But  
 of course resizing and reallocation would be a bit more complicated.

In addition to the problems you mention, there is also that of alignment requirements. Even if the memory lost is only 4 bytes for that int of length, if the data requires alignment of N bytes, the actual loss will be N bytes. This is of course much more of a problem with smaller than with larger arrays. -- Simen
May 30 2010