digitalmars.D.learn - Question about arrays
- Stephen Jones (7/7) Apr 21 2012 My C programming lies in cobwebs but from memory an array was a
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (21/28) Apr 21 2012 Yes and no. :) What you are describing is the feature where an array
- Steven Schveighoffer (7/15) Apr 23 2012 Technically speaking, the number of elements comes first in the memory ...
- Andrej Mitrovic (26/33) Apr 21 2012 D array -> struct of a length and pointer to the first element.
- Stephen Jones (20/20) Apr 22 2012 Thanks for the replies. I am still uncertain about something. The
- jerro (57/77) Apr 22 2012 Dynamic arrays in D are represented with a struct containing
- jerro (7/86) Apr 22 2012 Just to clarify, .ptr and .length aren't really fields, they
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (31/38) Apr 22 2012 The documentation may be incorrect because int[5] is never a slice. It
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]?
Apr 21 2012
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
Apr 21 2012
On Sat, 21 Apr 2012 18:25:44 -0400, Ali =C3=87ehreli <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 h= ad = to look it up in druntime to be sure!) is a testament to how = well-encapsulated D slices actually are. -Steve
Apr 23 2012
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
Apr 21 2012
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.
Apr 22 2012
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
Apr 22 2012
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: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.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
Apr 22 2012
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
Apr 22 2012