www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Initializing static arrays without specifying size

reply Ziad <hatahet gmail.com> writes:
Hi all,

I was wondering how I would go about initializing a static array
without explicitly specifying how big it is, given I lay out the
contents.

For example, if I do:

int[] a = [1, 2, 3, 4, 5];
auto a = [1, 2, 3, 4, 5];

both statements would result in a heap allocated array (slice). If I
want a static array:

int[5] a = [1, 2, 3, 4, 5];

I'd have to specify the size in advance (5 in this case), which
means that adding extra elements later on would require that the
size be update.

Is there a way to let the compiler automatically determine the size
based on the argument list?
Aug 01 2010
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Ziad:

 Is there a way to let the compiler automatically determine the size
 based on the argument list?
I don't know a clean way to do it. See the "related enhancement" here: http://d.puremagic.com/issues/show_bug.cgi?id=3849 With other people I have proposed the syntax: int[$] a = [1, 2, 3]; But so far Walter has not shown interest. Bye, bearophile
Aug 01 2010
prev sibling parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Mon, Aug 2, 2010 at 00:28, Ziad <hatahet gmail.com> wrote:

 If I want a static array:

 int[5] a = [1, 2, 3, 4, 5];

 I'd have to specify the size in advance (5 in this case), which
 means that adding extra elements later on would require that the
 size be update.

 Is there a way to let the compiler automatically determine the size
 based on the argument list?
Would a template-based solution be OK? import std.stdio, std.traits; CommonType!T[T.length] staticArray(T...)(T vals) if ((T.length > 0) && is(CommonType!T)) { return [vals]; } void main() { auto a = staticArray(0,1,2,3,4); writeln(typeof(a).stringof); // int[5u] auto b = staticArray(3.14); writeln(typeof(b).stringof); // double[1u] auto mixed = staticArray(0,1,2,3,4, 3.14); writeln(typeof(mixed).stringof); // double[6u] } Philippe
Aug 01 2010
parent reply bearophile <bearophileHUGS lycos.com> writes:
Philippe Sigaud:

 Would a template-based solution be OK?
 
 import std.stdio, std.traits;
 
 CommonType!T[T.length] staticArray(T...)(T vals)
     if ((T.length > 0) && is(CommonType!T))
 {
     return [vals];
 }
That's one solution, but code like that is most useful when your arrays liters are long (because if they are little you can just count the items and avoid using staticArray), this is an example (I have used printf to avoid the metric ton of functions and templates used by writeln): import std.c.stdio: printf; import std.traits: CommonType; CommonType!T[T.length] staticArray(T...)(T vals) if (T.length && is(CommonType!T)) { return [vals]; } void main() { auto a = staticArray(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280, 290, 300, 310, 320, 330, 340, 350, 360, 370, 380, 390, 400, 410, 420, 430, 440, 450, 460, 470, 480, 490, 500, 510, 520, 530, 540, 550, 560, 570, 580, 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800, 810, 820, 830, 840, 850, 860, 870, 880, 890, 900, 910, 920, 930, 940, 950, 960, 970, 980, 990); printf("%d\n", a[2]); } This is the asm of the staticArray: _D5test2217__T11staticArrayTiZFiiZG100i comdat L0: push EAX push ESI push EDI push dword ptr 010h[ESP] push dword ptr 018h[ESP] push dword ptr 020h[ESP] push dword ptr 028h[ESP] push dword ptr 030h[ESP] push dword ptr 038h[ESP] push dword ptr 040h[ESP] push dword ptr 048h[ESP] push dword ptr 050h[ESP] push dword ptr 058h[ESP] push dword ptr 060h[ESP] push dword ptr 068h[ESP] push dword ptr 070h[ESP] push dword ptr 078h[ESP] push dword ptr 080h[ESP] push dword ptr 088h[ESP] push dword ptr 090h[ESP] push dword ptr 098h[ESP] push dword ptr 0A0h[ESP] push dword ptr 0A8h[ESP] push dword ptr 0B0h[ESP] push dword ptr 0B8h[ESP] push dword ptr 0C0h[ESP] push dword ptr 0C8h[ESP] push dword ptr 0D0h[ESP] push dword ptr 0D8h[ESP] push dword ptr 0E0h[ESP] push dword ptr 0E8h[ESP] push dword ptr 0F0h[ESP] push dword ptr 0F8h[ESP] push dword ptr 0100h[ESP] push dword ptr 0108h[ESP] push dword ptr 0110h[ESP] push dword ptr 0118h[ESP] push dword ptr 0120h[ESP] push dword ptr 0128h[ESP] push dword ptr 0130h[ESP] push dword ptr 0138h[ESP] push dword ptr 0140h[ESP] push dword ptr 0148h[ESP] push dword ptr 0150h[ESP] push dword ptr 0158h[ESP] push dword ptr 0160h[ESP] push dword ptr 0168h[ESP] push dword ptr 0170h[ESP] push dword ptr 0178h[ESP] push dword ptr 0180h[ESP] push dword ptr 0188h[ESP] push dword ptr 0190h[ESP] push dword ptr 0198h[ESP] push dword ptr 01A0h[ESP] push dword ptr 01A8h[ESP] push dword ptr 01B0h[ESP] push dword ptr 01B8h[ESP] push dword ptr 01C0h[ESP] push dword ptr 01C8h[ESP] push dword ptr 01D0h[ESP] push dword ptr 01D8h[ESP] push dword ptr 01E0h[ESP] push dword ptr 01E8h[ESP] push dword ptr 01F0h[ESP] push dword ptr 01F8h[ESP] push dword ptr 0200h[ESP] push dword ptr 0208h[ESP] push dword ptr 0210h[ESP] push dword ptr 0218h[ESP] push dword ptr 0220h[ESP] push dword ptr 0228h[ESP] push dword ptr 0230h[ESP] push dword ptr 0238h[ESP] push dword ptr 0240h[ESP] push dword ptr 0248h[ESP] push dword ptr 0250h[ESP] push dword ptr 0258h[ESP] push dword ptr 0260h[ESP] push dword ptr 0268h[ESP] push dword ptr 0270h[ESP] push dword ptr 0278h[ESP] push dword ptr 0280h[ESP] push dword ptr 0288h[ESP] mov ECX,offset FLAT:_D14TypeInfo_G100i6__initZ push dword ptr 0290h[ESP] push dword ptr 0298h[ESP] push dword ptr 02A0h[ESP] push dword ptr 02A8h[ESP] push dword ptr 02B0h[ESP] push dword ptr 02B8h[ESP] push dword ptr 02C0h[ESP] push dword ptr 02C8h[ESP] push dword ptr 02D0h[ESP] push dword ptr 02D8h[ESP] push dword ptr 02E0h[ESP] push dword ptr 02E8h[ESP] push dword ptr 02F0h[ESP] push dword ptr 02F8h[ESP] push dword ptr 0300h[ESP] push dword ptr 0308h[ESP] push dword ptr 0310h[ESP] push dword ptr 0318h[ESP] push dword ptr 0320h[ESP] push dword ptr 0328h[ESP] push 064h push ECX call near ptr __d_arrayliteralT mov ESI,EAX mov EDI,01A0h[ESP] mov ECX,064h rep movsd add ESP,0198h mov EAX,8[ESP] pop EDI pop ESI pop ECX ret 0190h And you essentially have one similar function each time you use staticArray. This is why in my answer I have said I don't know any good solution to this problem and this is why I have proposed the enhancement [$] syntax. In my code I count the items in some way (with Python, or I assign the literal to a dynamic array, print its length and then modify the code replacing the dynamic array with the printed number). Bye, bearophile
Aug 02 2010
next sibling parent reply BCS <none anon.com> writes:
Hello bearophile,

 Philippe Sigaud:
 
 Would a template-based solution be OK?
 
 import std.stdio, std.traits;
 
 CommonType!T[T.length] staticArray(T...)(T vals)
 if ((T.length > 0) && is(CommonType!T))
 {
 return [vals];
 }
That's one solution, but code like that is most useful when your arrays liters are long (because if they are little you can just count the items and avoid using staticArray), this is an example (I have used printf to avoid the metric ton of functions and templates used by writeln): import std.c.stdio: printf; import std.traits: CommonType; CommonType!T[T.length] staticArray(T...)(T vals) if (T.length && is(CommonType!T)) { return [vals]; } void main() { auto a = staticArray(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
...
 990);
 printf("%d\n", a[2]);
 }
 This is the asm of the staticArray:
 
 _D5test2217__T11staticArrayTi  ZFii  ZG100i
 comdat
 L0:     push    EAX
 push    ESI
 push    EDI
 push    dword ptr 010h[ESP]
...
 push    dword ptr 0328h[ESP]
 push    064h
 push    ECX
 call    near ptr __d_arrayliteralT
 mov ESI,EAX
 mov EDI,01A0h[ESP]
 mov ECX,064h
 rep
 movsd
 add ESP,0198h
 mov EAX,8[ESP]
 pop EDI
 pop ESI
 pop ECX
 ret 0190h
Is that with or without inline? If that doesn't inline away to a memcopy then it looks like an optimization opportunity to me.
 And you essentially have one similar function each time you use
 staticArray. This is why in my answer I have said I don't know any
 good solution to this problem and this is why I have proposed the
 enhancement [$] syntax.
 
 In my code I count the items in some way (with Python, or I assign the
 literal to a dynamic array, print its length and then modify the code
 replacing the dynamic array with the printed number).
 
 Bye,
 bearophile
-- ... <IXOYE><
Aug 02 2010
parent bearophile <bearophileHUGS lycos.com> writes:
BCS:
 Is that with or without inline? If that doesn't inline away to a memcopy 
 then it looks like an optimization opportunity to me.
That's with inline, but if you don't use inline the result is the same, because that is the asm of a function, not of its caller (the main), so DMD keeps the not inlined function around anyway even when it inlines it. So in your binary you find all the staticArray() you have instantiated/used. This is the main (compiled with -O -release -inline, dmd 2.047): __Dmain comdat L0: sub ESP,0194h push 0190h push 03DEh push 03D4h push 03CAh push 03C0h push 03B6h push 03ACh push 03A2h push 0398h push 038Eh push 0384h push 037Ah push 0370h push 0366h push 035Ch push 0352h push 0348h push 033Eh push 0334h push 032Ah push 0320h push 0316h push 030Ch push 0302h push 02F8h push 02EEh push 02E4h push 02DAh push 02D0h push 02C6h push 02BCh push 02B2h push 02A8h push 029Eh push 0294h push 028Ah push 0280h push 0276h push 026Ch push 0262h push 0258h push 024Eh push 0244h push 023Ah push 0230h push 0226h push 021Ch push 0212h push 0208h push 01FEh push 01F4h push 01EAh push 01E0h push 01D6h push 01CCh push 01C2h push 01B8h push 01AEh push 01A4h push 019Ah push 0190h push 0186h push 017Ch push 0172h push 0168h push 015Eh push 0154h push 014Ah push 0140h push 0136h push 012Ch push 0122h push 0118h push 010Eh push 0104h push 0FAh push 0F0h push 0E6h push 0DCh push 0D2h push 0C8h push 0BEh mov EAX,offset FLAT:_D14TypeInfo_G100i6__initZ push 0B4h push 0AAh push 0A0h push 096h push 08Ch push 082h push 078h push 06Eh push 064h push 05Ah push 050h push 046h push 03Ch push 032h push 028h push 01Eh push 014h push 0Ah push 0 push 064h push EAX call near ptr __d_arrayliteralT add ESP,0198h push EAX lea ECX,0Ch[ESP] push ECX call near ptr _memcpy mov EDX,offset FLAT:_DATA push dword ptr 018h[ESP] push EDX call near ptr _printf add ESP,014h add ESP,0194h xor EAX,EAX ret Bye, bearophile
Aug 02 2010
prev sibling next sibling parent Ziad Hatahet <hatahet gmail.com> writes:
Thanks for your feedback Philippe and bearophile :)

Cheers,
-- Ziad
Aug 02 2010
prev sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Mon, Aug 2, 2010 at 14:15, bearophile <bearophileHUGS lycos.com> wrote:

 That's one solution, but code like that is most useful when your arrays
 liters are long (because if they are little you can just count the items and
 avoid using staticArray)
Yes, but as Ziad said: "If I want a static array (...) I'd have to specify the size in advance (5 in this case), which means that adding extra elements later on would require that the size be update." So small-size arrays _are_ a possibility. Ziad:
 Thanks for your feedback Philippe and bearophile :)
If you understand the code, very well. If not, say so. I know I'd have been unable to understand it two years ago. Philippe
Aug 02 2010