View mode: basic / threaded / horizontal-split · Log in · Help
April 21, 2012
Question about arrays
My C programming lies in cobwebs but from memory an array was a 
pointer to the zeroth index of a set of uniformly sized chunks of 
memory. I am perplexed to find that in D a call to an array (of 
float vertices for example) cannot be accomplished by handing &v 
to functions that need the zeroth index. Is this because D holds 
a pointer to an array object and the zeroth index is accessed 
(via compiler background work) to  &v[0]?
April 21, 2012
Re: Question about arrays
On 04/21/2012 03:05 PM, Stephen Jones wrote:
> My C programming lies in cobwebs but from memory an array was a pointer
> to the zeroth index of a set of uniformly sized chunks of memory.

Yes and no. :) What you are describing is the feature where an array 
decays to what you describe.

But there is also the concept of array in C, which is a collection of 
elements side by side. When you apply sizeof to such a thing, you get 
the size of the whole thing. So, the whole thing is the array.

But you are right, when passed to functions, they decay to "pointer to 
first element."

> I am
> perplexed to find that in D a call to an array (of float vertices for
> example) cannot be accomplished by handing &v to functions that need the
> zeroth index. Is this because D holds a pointer to an array object and
> the zeroth index is accessed (via compiler background work) to &v[0]?

In D, arrays are what they should have been in C :). A pointer and a 
size. Something the equivalent of the following (for the int type):

struct int_Array
{
    int * elements;
    size_t number_of_elements;
}

Correction: That is a slice (aka dynamic array). There is also the 
fixed-length arrays (aka static arrays) in D.

If you pass the address of a slice, you are passing the address of such 
a struct variable. So don't bother with the address at all, just pass 
the array object by value.

Ali
April 21, 2012
Re: Question about arrays
On 4/22/12, Stephen Jones <siwenjo@gmail.com> wrote:
> My C programming lies in cobwebs but from memory an array was a
> pointer to the zeroth index of a set of uniformly sized chunks of
> memory. I am perplexed to find that in D a call to an array (of
> float vertices for example) cannot be accomplished by handing &v
> to functions that need the zeroth index. Is this because D holds
> a pointer to an array object and the zeroth index is accessed
> (via compiler background work) to  &v[0]?
>

D array -> struct of a length and pointer to the first element.

If you want to pass arrays to C functions you can do either of these:
float[] arr;
cFunc(arr.ptr, arr.length)
cFunc(&arr[0], arr.length);

I'm assuming the C function needs a length. Maybe this will make things clearer:

void main()
{
   int[] a = new int[](10);
   size_t count = *cast(size_t*)&a;  // first element is the count
   assert(count == 10);

   a[0] = 5;
   a[1] = 100;

   int* iter = &a[0];  // or use a.ptr
   assert(*iter == 5);
   ++iter;
   assert(*iter == 100);
}

Of course you wouldn't really use this style of code in D, but if you
have to pass arrays to C use the .ptr field or &arr[0]. On the other
hand, passing jagged multidimensional arrays via .ptr to C functions
isn't going to work out of the box, but that's another topic (and
there's a workaround).

A good article about D arrays/slices is here:
http://dlang.org/d-array-article.html
April 22, 2012
Re: Question about arrays
Thanks for the replies. I am still uncertain about something. The 
documentation distinguishes between dynamic slices (int[5] a = 
new int[5]) which are managed by the runtime, and stack allocated 
arrays (int[5] b). The problem I have is this. I want to be 
loading vertex positions and tex-coords of data exported from 
Blender into openGL vertex buffers. Basically the float data 
needs to be extracted from a file and passed up to the graphic 
card's memory but to do so it needs to transit through the CPU 
memory. Ideally I want to:
    a) load the data from the file into an array built upon the 
stack and owned by a function
    b) generate the vbo id and send the data off to the graphics 
card
    c) pass the id back into a class held in managed memory
    d) quit the function thus releasing the array on the stack

My confusion is, if the syntax for both stack based and managed 
memory arrays is the same (&v[0] or &v.ptr) then both must be 
objects. I guess the difference is that stack based are of 
constant length, whereas slices are dynamic because they are 
managed by the runtime.
April 22, 2012
Re: Question about arrays
On Sunday, 22 April 2012 at 22:17:11 UTC, Stephen Jones wrote:
> Thanks for the replies. I am still uncertain about something. 
> The documentation distinguishes between dynamic slices (int[5] 
> a = new int[5]) which are managed by the runtime, and stack 
> allocated arrays (int[5] b). The problem I have is this. I want 
> to be loading vertex positions and tex-coords of data exported 
> from Blender into openGL vertex buffers. Basically the float 
> data needs to be extracted from a file and passed up to the 
> graphic card's memory but to do so it needs to transit through 
> the CPU memory. Ideally I want to:
>     a) load the data from the file into an array built upon the 
> stack and owned by a function
>     b) generate the vbo id and send the data off to the 
> graphics card
>     c) pass the id back into a class held in managed memory
>     d) quit the function thus releasing the array on the stack
>
> My confusion is, if the syntax for both stack based and managed 
> memory arrays is the same (&v[0] or &v.ptr) then both must be 
> objects. I guess the difference is that stack based are of 
> constant length, whereas slices are dynamic because they are 
> managed by the runtime.

Dynamic arrays in D are represented with a struct containing
a pointer to the start of data and a length. Static arrays are
represented in the same way as they are in C - just the data is
saved, the length is known at compile time and the pointer to data
is computed from the stack frame pointer (or a pointer to
struct if the static array is contained within a struct) and the
offset which is also know at compile time, the same way the 
pointers
to primitive types are computed.  For example the following D 
program:

import std.stdio;

auto vp(T)(T* a){ return cast(void*) a; }

struct S
{
        int[8] a;
        int[8] b;
        int[]  c;
        int[8] d;
}

void main()
{
        S s;
        writeln( vp(&s.a) - vp(&s.a[0]));
        writeln(vp(&s.b) - vp(&s.a));
        writeln(vp(&s.c) - vp(&s.b));
        writeln(vp(&s.d) - vp(&s.c));
}

and the following C program:

#include <stdio.h>

#define vp(a) (void*)(a)

typedef struct
{
        int* ptr;
        size_t length;
} IntArray;

typedef struct
{
        int a[8];
        int b[8];
        IntArray  c;
        int d[8];
} S;

int main()
{
        S s;
        printf("%d\n", vp(&s.a) - vp(&s.a[0]));
        printf("%d\n", vp(&s.b) - vp(&s.a));
        printf("%d\n", vp(&s.c) - vp(&s.b));
        printf("%d\n", vp(&s.d) - vp(&s.c));
        return 0;
}

both print

0
32
32
16
April 22, 2012
Re: Question about arrays
On Sunday, 22 April 2012 at 23:01:26 UTC, jerro wrote:
> On Sunday, 22 April 2012 at 22:17:11 UTC, Stephen Jones wrote:
>> Thanks for the replies. I am still uncertain about something. 
>> The documentation distinguishes between dynamic slices (int[5] 
>> a = new int[5]) which are managed by the runtime, and stack 
>> allocated arrays (int[5] b). The problem I have is this. I 
>> want to be loading vertex positions and tex-coords of data 
>> exported from Blender into openGL vertex buffers. Basically 
>> the float data needs to be extracted from a file and passed up 
>> to the graphic card's memory but to do so it needs to transit 
>> through the CPU memory. Ideally I want to:
>>    a) load the data from the file into an array built upon the 
>> stack and owned by a function
>>    b) generate the vbo id and send the data off to the 
>> graphics card
>>    c) pass the id back into a class held in managed memory
>>    d) quit the function thus releasing the array on the stack
>>
>> My confusion is, if the syntax for both stack based and 
>> managed memory arrays is the same (&v[0] or &v.ptr) then both 
>> must be objects. I guess the difference is that stack based 
>> are of constant length, whereas slices are dynamic because 
>> they are managed by the runtime.
>
> Dynamic arrays in D are represented with a struct containing
> a pointer to the start of data and a length. Static arrays are
> represented in the same way as they are in C - just the data is
> saved, the length is known at compile time and the pointer to 
> data
> is computed from the stack frame pointer (or a pointer to
> struct if the static array is contained within a struct) and the
> offset which is also know at compile time, the same way the 
> pointers
> to primitive types are computed.  For example the following D 
> program:
>
> import std.stdio;
>
> auto vp(T)(T* a){ return cast(void*) a; }
>
> struct S
> {
>         int[8] a;
>         int[8] b;
>         int[]  c;
>         int[8] d;
> }
>
> void main()
> {
>         S s;
>         writeln( vp(&s.a) - vp(&s.a[0]));
>         writeln(vp(&s.b) - vp(&s.a));
>         writeln(vp(&s.c) - vp(&s.b));
>         writeln(vp(&s.d) - vp(&s.c));
> }
>
> and the following C program:
>
> #include <stdio.h>
>
> #define vp(a) (void*)(a)
>
> typedef struct
> {
>         int* ptr;
>         size_t length;
> } IntArray;
>
> typedef struct
> {
>         int a[8];
>         int b[8];
>         IntArray  c;
>         int d[8];
> } S;
>
> int main()
> {
>         S s;
>         printf("%d\n", vp(&s.a) - vp(&s.a[0]));
>         printf("%d\n", vp(&s.b) - vp(&s.a));
>         printf("%d\n", vp(&s.c) - vp(&s.b));
>         printf("%d\n", vp(&s.d) - vp(&s.c));
>         return 0;
> }
>
> both print
>
> 0
> 32
> 32
> 16

Just to clarify, .ptr and .length aren't really fields, they
are properties. Dynamic arrays are actually represented as
structs containing a pointer and a length, but static arrays
are not. The fact that they have .ptr and .length properties
does not imply they are represented as structs with .ptr and
.length fields.
April 23, 2012
Re: Question about arrays
On 04/22/2012 03:17 PM, Stephen Jones wrote:
> Thanks for the replies. I am still uncertain about something. The
> documentation distinguishes between dynamic slices (int[5] a = new
> int[5])

The documentation may be incorrect because int[5] is never a slice. It 
is a fixed-length array.

As an aside, I don't like calling fixed-length arrays static arrays, 
because static implies compile time. Fine, the length is known at 
compile time but as your code above demonstrates, the storage can be 
allocated at runtime, dynamically.

> which are managed by the runtime, and stack allocated arrays
> (int[5] b).

"Stack allocated" may also be misleading because a fixed-length array 
can be a part of a type that is allocated dynamically:

class Foo
{
    int[5] b;  // <-- not on the stack
}

As jerro explained, a slice is a pointer to the first element and a 
length. A fixed-length array is N elements side by side.

> My confusion is, if the syntax for both stack based and managed memory
> arrays is the same (&v[0] or &v.ptr)

You must have meant &v[0] and v.ptr. It is the same for both types:

    // fixed-length
    {
        int[5] a = new int[5];
        auto firstElem_1 = a.ptr;
        auto firstElem_2 = &a[0];
        assert(firstElem_1 == firstElem_2);
    }

    // slice
    {
        int[] a = new int[5];
        auto firstElem_1 = a.ptr;
        auto firstElem_2 = &a[0];
        assert(firstElem_1 == firstElem_2);
    }

Ali
April 23, 2012
Re: Question about arrays
On Sat, 21 Apr 2012 18:25:44 -0400, Ali Çehreli <acehreli@yahoo.com> wrote:

> In D, arrays are what they should have been in C :). A pointer and a  
> size. Something the equivalent of the following (for the int type):
>
> struct int_Array
> {
>      int * elements;
>      size_t number_of_elements;
> }

Technically speaking, the number of elements comes first in the memory  
layout.  The fact that even seasoned D coders get it wrong (in fact, I had  
to look it up in druntime to be sure!) is a testament to how  
well-encapsulated D slices actually are.

-Steve
Top | Discussion index | About this forum | D home