www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - How do I initialize arrays in D????

reply Ron <Ron_member pathlink.com> writes:
The C way of:

void[16] *routines = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};

does NOT work. I get the message:
"Error: a struct is not a valid initializer for a void[16]*"

Same thing with a char array (same way, just w/ string data), but the error
message is:
"Error: a struct is not a valid initializer for a char[32]*"

How do you init these arrays?

--Ron
Feb 22 2005
next sibling parent Derek Parnell <derek psych.ward> writes:
On Wed, 23 Feb 2005 07:11:23 +0000 (UTC), Ron wrote:

 The C way of:
 
 void[16] *routines = {
 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0
 };
 
 does NOT work. I get the message:
 "Error: a struct is not a valid initializer for a void[16]*"
 
 Same thing with a char array (same way, just w/ string data), but the error
 message is:
 "Error: a struct is not a valid initializer for a char[32]*"
 
 How do you init these arrays?
 
 --Ron

There is currently no way to initialize arrays to a literal (static) value at compile time. All array initialization must be done at run time. BTW, most things are automatically initialized to zero/null on declaration. To initialize an array *before* main() gets control, use a module constructor... int[16] val; static this() { // This is run once, just prior to main(). val[0] = 1; val[1] = 3; val[2] = 6; val[3] = 8; val[4] = 2; val[5] = 11; val[6] = 51; val[7] = 8; val[8] = 42; val[9] = 100; val[10] = 90; val[11] = 33; val[12] = 45; val[13] = -32; val[14] = 0; val[15] = 12; } -- Derek Melbourne, Australia 23/02/2005 6:13:07 PM
Feb 22 2005
prev sibling next sibling parent reply John Reimer <brk_6502 yahoo.com> writes:
Ron wrote:
 The C way of:
 
 void[16] *routines = {
 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0
 };
 
 does NOT work. I get the message:
 "Error: a struct is not a valid initializer for a void[16]*"
 
 Same thing with a char array (same way, just w/ string data), but the error
 message is:
 "Error: a struct is not a valid initializer for a char[32]*"
 
 How do you init these arrays?
 
 --Ron
 
 

I'm not sure what you intended here. The above is a single pointer to an array of 16 void types. So you won't succeed in trying to assign the array values to a single pointer. So doing this is valid: # void[16] *routines = null; But if you wanted to assign 16 values to an array of 16 void pointers, try this: # void*[16] routines = null; The above is a nifty shorthand for assigning "null" to all 16 variables in the array. You could do it the long way like this: # // Global variable # # void*[16] routines = [ # null, null, null, null, null, null, null, null, # null, null, null, null, null, null, null, null # ]; The above is a static initializer, so it only works for global variables or static variables (variables lasting the lifetime of the program: the local equivalent to a global variable). Notice that brackets are used instead of braces. If you wanted to do the above inside a function, you would do: # static void*[16] routines = [ # null, null, null, null, null, null, null, null, # null, null, null, null, null, null, null, null # ]; I hope that helps you. - John R.
Feb 22 2005
next sibling parent reply John Reimer <brk_6502 yahoo.com> writes:
John Reimer wrote:
 Ron wrote:
 
 The C way of:

 void[16] *routines = {
 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0
 };

 does NOT work. I get the message:
 "Error: a struct is not a valid initializer for a void[16]*"

 Same thing with a char array (same way, just w/ string data), but the 
 error
 message is:
 "Error: a struct is not a valid initializer for a char[32]*"

 How do you init these arrays?

 --Ron

I'm not sure what you intended here. The above is a single pointer to an array of 16 void types. So you won't succeed in trying to assign the array values to a single pointer. So doing this is valid: # void[16] *routines = null; But if you wanted to assign 16 values to an array of 16 void pointers, try this: # void*[16] routines = null; The above is a nifty shorthand for assigning "null" to all 16 variables in the array. You could do it the long way like this: # // Global variable # # void*[16] routines = [ # null, null, null, null, null, null, null, null, # null, null, null, null, null, null, null, null # ]; The above is a static initializer, so it only works for global variables or static variables (variables lasting the lifetime of the program: the local equivalent to a global variable). Notice that brackets are used instead of braces. If you wanted to do the above inside a function, you would do: # static void*[16] routines = [ # null, null, null, null, null, null, null, null, # null, null, null, null, null, null, null, null # ]; I hope that helps you. - John R.

I should point out, though, that initializing static/global values to null/0 is not necessary since D does that automatically on program start.
Feb 22 2005
next sibling parent reply Manfred Nowak <svv1999 hotmail.com> writes:
John Reimer <brk_6502 yahoo.com> wrote:
[...]
 I should point out, though, that initializing static/global
 values to null/0 is not necessary since D does that
 automatically on program start. 

I think that this is misleading. As Walter pointed out several times the purpose of the default initializations is to prevent the coder and tester to have an unreproducible behaviour because of a misssing initialization. That is, that the default initializing is not meant to spare the coder the coding of the initializer. Therefore the coder is to make clear that he wants the initializer to be identical to the current default initializer value. On my opinion the specs should make clear that although the default initializer is defined it is illegal to rely on the value of the default initializer. -manfred
Feb 23 2005
parent John Reimer <brk_6502 yahoo.com> writes:
Manfred Nowak wrote:
 John Reimer <brk_6502 yahoo.com> wrote:
 [...]
 
I should point out, though, that initializing static/global
values to null/0 is not necessary since D does that
automatically on program start. 

I think that this is misleading. As Walter pointed out several times the purpose of the default initializations is to prevent the coder and tester to have an unreproducible behaviour because of a misssing initialization. That is, that the default initializing is not meant to spare the coder the coding of the initializer. Therefore the coder is to make clear that he wants the initializer to be identical to the current default initializer value. On my opinion the specs should make clear that although the default initializer is defined it is illegal to rely on the value of the default initializer. -manfred

Good point. I agree. It is good practice to do initializations yourself.
Feb 23 2005
prev sibling parent reply David Medlock <amedlock nospam.org> writes:
John Reimer wrote:

 
 I should point out, though, that initializing static/global values to 
 null/0 is not necessary since D does that automatically on program start.

In doing some stuff with floating point math I was stumped until I noticed the default value for float/double/real is NaN. (I am not sure why, though I am sure there is a good reason for this) FYI
Feb 23 2005
next sibling parent John Reimer <brk_6502 yahoo.com> writes:
David Medlock wrote:
 John Reimer wrote:
 
 I should point out, though, that initializing static/global values to 
 null/0 is not necessary since D does that automatically on program start.

In doing some stuff with floating point math I was stumped until I noticed the default value for float/double/real is NaN. (I am not sure why, though I am sure there is a good reason for this) FYI

True. I should have clarified that the default values are not always 0. It depends on the variable type. So like Manfred said, it's important to realize that the programmer still is responsible for initializing these variables. - John R.
Feb 23 2005
prev sibling parent Georg Wrede <georg.wrede nospam.org> writes:
David Medlock wrote:
 John Reimer wrote:
 
 I should point out, though, that initializing static/global values to 
 null/0 is not necessary since D does that automatically on program start.

In doing some stuff with floating point math I was stumped until I noticed the default value for float/double/real is NaN. (I am not sure why, though I am sure there is a good reason for this)

Walter (and most of us?) think that initialising floats to something obviously "wrong" is better than letting them be zero. The idea being that you're not supposed to use uninitialised variables anyway, so forgetting to do this jumps into your face at once. (I'm under the impression that this would've be done with ints too, but there's unfortunately no way to Officially Define a NAN for the int types.) Forgetting to initialise something that's zero is less obvious. And happens a lot, especially in the future, when a lot of VB-folks etc. come here. Initialising floats to NANs is cheaper and easier than having the compiler do enormous checks on whether this or that variable actually _could_ be used before initial assignment in complicated code. That is what the IEEE recommends, anyway. ----------- OT: a little trivia + personal opinion: Had I designed the IEEE format, I'd have the bit pattern "all-zeros" represent NAN, so that it would be fiercely obvious what the intent of NAN is. Well, they didn't. 000000 means +0. (Yeah, plus, not just zero.) Interestingly, there are several bit patterns that mean NAN. One of them is all-ones. Oh, and then there are _two_ different NANs, one for (eh, might I say) regular NANs, and the other for Serious NANs. They're called QNAN and SNAN. The former is pretty much what would be used if an intermediate result is "not nice", and the latter for "oh crap" situations. Or at least _should_ be used. How exactly they work in D math isn't something I don't remember having studied.
Feb 23 2005
prev sibling parent reply Ron <Ron_member pathlink.com> writes:
In article <cvhbhn$14r$1 digitaldaemon.com>, John Reimer says...
Ron wrote:
 The C way of:
 
 void[16] *routines = {
 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0
 };
 
 does NOT work. I get the message:
 "Error: a struct is not a valid initializer for a void[16]*"
 
 Same thing with a char array (same way, just w/ string data), but the error
 message is:
 "Error: a struct is not a valid initializer for a char[32]*"
 
 How do you init these arrays?
 
 --Ron
 
 

I'm not sure what you intended here. The above is a single pointer to an array of 16 void types. So you won't succeed in trying to assign the array values to a single pointer. So doing this is valid: # void[16] *routines = null; But if you wanted to assign 16 values to an array of 16 void pointers, try this: # void*[16] routines = null; The above is a nifty shorthand for assigning "null" to all 16 variables in the array. You could do it the long way like this: # // Global variable # # void*[16] routines = [ # null, null, null, null, null, null, null, null, # null, null, null, null, null, null, null, null # ]; The above is a static initializer, so it only works for global variables or static variables (variables lasting the lifetime of the program: the local equivalent to a global variable). Notice that brackets are used instead of braces. If you wanted to do the above inside a function, you would do: # static void*[16] routines = [ # null, null, null, null, null, null, null, null, # null, null, null, null, null, null, null, null # ]; I hope that helps you. - John R.

Thanks John, that did work... *routines was a pointer to an array of 16 void pointers. I'm having a little trouble in the same area with a char[32] *array (pointer to 32 strings of var. length). The error I get is: "d/isrs.d: In function `_staticCtor': d/isrs.d:0: error: aggregate value used where an integer was expected" The code looks like this: char[32] *exception_messages; // global static this() { *exception_messages[0] = cast(char)"Division By Zero"; *exception_messages[1] = cast(char)"Debug"; *exception_messages[2] = cast(char)"Non Maskable Interrupt"; *exception_messages[3] = cast(char)"Breakpoint"; *exception_messages[4] = cast(char)"Into Detected Overflow"; *exception_messages[5] = cast(char)"Out of Bounds"; *exception_messages[6] = cast(char)"Invalid Opcode"; *exception_messages[7] = cast(char)"No Coprocessor"; *exception_messages[8] = cast(char)"Double Fault"; *exception_messages[9] = cast(char)"Coprocessor Segment Overrun"; *exception_messages[10] = cast(char)"Bad TSS"; *exception_messages[11] = cast(char)"Segment Not Present"; *exception_messages[12] = cast(char)"Stack Fault"; *exception_messages[13] = cast(char)"General Protection Fault"; *exception_messages[14] = cast(char)"Page Fault"; *exception_messages[15] = cast(char)"Unknown Interrupt"; *exception_messages[16] = cast(char)"Coprocessor Fault"; *exception_messages[17] = cast(char)"Alignment Check"; *exception_messages[18] = cast(char)"Machine Check"; *exception_messages[19] = cast(char)"Reserved"; *exception_messages[20] = cast(char)"Reserved"; *exception_messages[21] = cast(char)"Reserved"; *exception_messages[22] = cast(char)"Reserved"; *exception_messages[23] = cast(char)"Reserved"; *exception_messages[24] = cast(char)"Reserved"; *exception_messages[25] = cast(char)"Reserved"; *exception_messages[26] = cast(char)"Reserved"; *exception_messages[27] = cast(char)"Reserved"; *exception_messages[28] = cast(char)"Reserved"; *exception_messages[29] = cast(char)"Reserved"; *exception_messages[30] = cast(char)"Reserved"; *exception_messages[31] = cast(char)"Reserved"; } Thanks in advance, --Ron
Feb 24 2005
next sibling parent brad domain.invalid writes:
 char[32] *exception_messages;  // global
 
 static this()
 {
 *exception_messages[0] = cast(char)"Division By Zero";
 }

<snip> try this char*[32] exception_messages; static this() { exception_messages[0] = "Division by Zero"; } having your type as "char[][32] exception_messages" also works. Brad
Feb 24 2005
prev sibling parent reply Derek <derek psych.ward> writes:
On Thu, 24 Feb 2005 20:16:07 +0000 (UTC), Ron wrote:

[snip]
 The code looks like this:

Or maybe ... import std.stdio; private char[][] exception_messages; char[] GetMessageText(int id) { if (id >= 0 && id < exception_messages.length) return exception_messages[id].dup; else return ""; } static this() { exception_messages ~= "Division By Zero"; exception_messages ~= "Debug"; exception_messages ~= "Non Maskable Interrupt"; exception_messages ~= "Breakpoint"; exception_messages ~= "Into Detected Overflow"; exception_messages ~= "Out of Bounds"; exception_messages ~= "Invalid Opcode"; exception_messages ~= "No Coprocessor"; exception_messages ~= "Double Fault"; exception_messages ~= "Coprocessor Segment Overrun"; exception_messages ~= "Bad TSS"; exception_messages ~= "Segment Not Present"; exception_messages ~= "Stack Fault"; exception_messages ~= "General Protection Fault"; exception_messages ~= "Page Fault"; exception_messages ~= "Unknown Interrupt"; exception_messages ~= "Coprocessor Fault"; exception_messages ~= "Alignment Check"; exception_messages ~= "Machine Check"; } void main() { writefln("%s", GetMessageText(4)); } This makes sure that outside code cannot change the text of any message, and makes it easy to expand the list of messages in future. Also, no pointers involved. -- Derek Melbourne, Australia
Feb 24 2005
next sibling parent reply Ron <Ron_member pathlink.com> writes:
In article <1el83535hd3ja$.xafk5jfa77v5$.dlg 40tude.net>, Derek says...
On Thu, 24 Feb 2005 20:16:07 +0000 (UTC), Ron wrote:

[snip]
 The code looks like this:

Or maybe ... import std.stdio; private char[][] exception_messages; char[] GetMessageText(int id) { if (id >= 0 && id < exception_messages.length) return exception_messages[id].dup; else return ""; } static this() { exception_messages ~= "Division By Zero"; exception_messages ~= "Debug"; exception_messages ~= "Non Maskable Interrupt"; exception_messages ~= "Breakpoint"; exception_messages ~= "Into Detected Overflow"; exception_messages ~= "Out of Bounds"; exception_messages ~= "Invalid Opcode"; exception_messages ~= "No Coprocessor"; exception_messages ~= "Double Fault"; exception_messages ~= "Coprocessor Segment Overrun"; exception_messages ~= "Bad TSS"; exception_messages ~= "Segment Not Present"; exception_messages ~= "Stack Fault"; exception_messages ~= "General Protection Fault"; exception_messages ~= "Page Fault"; exception_messages ~= "Unknown Interrupt"; exception_messages ~= "Coprocessor Fault"; exception_messages ~= "Alignment Check"; exception_messages ~= "Machine Check"; } void main() { writefln("%s", GetMessageText(4)); } This makes sure that outside code cannot change the text of any message, and makes it easy to expand the list of messages in future. Also, no pointers involved. -- Derek Melbourne, Australia

Thanks Derek, but unfortunately I can't use the standard libs... I have to implement the std lib myself... Writing a toy OO kernel for a prog. class project. --Ron
Feb 24 2005
parent Derek Parnell <derek psych.ward> writes:
On Thu, 24 Feb 2005 21:53:37 +0000 (UTC), Ron wrote:

 In article <1el83535hd3ja$.xafk5jfa77v5$.dlg 40tude.net>, Derek says...
On Thu, 24 Feb 2005 20:16:07 +0000 (UTC), Ron wrote:

[snip]
 The code looks like this:

Or maybe ... import std.stdio; private char[][] exception_messages; char[] GetMessageText(int id) { if (id >= 0 && id < exception_messages.length) return exception_messages[id].dup; else return ""; } static this() { exception_messages ~= "Division By Zero"; exception_messages ~= "Debug"; exception_messages ~= "Non Maskable Interrupt"; exception_messages ~= "Breakpoint"; exception_messages ~= "Into Detected Overflow"; exception_messages ~= "Out of Bounds"; exception_messages ~= "Invalid Opcode"; exception_messages ~= "No Coprocessor"; exception_messages ~= "Double Fault"; exception_messages ~= "Coprocessor Segment Overrun"; exception_messages ~= "Bad TSS"; exception_messages ~= "Segment Not Present"; exception_messages ~= "Stack Fault"; exception_messages ~= "General Protection Fault"; exception_messages ~= "Page Fault"; exception_messages ~= "Unknown Interrupt"; exception_messages ~= "Coprocessor Fault"; exception_messages ~= "Alignment Check"; exception_messages ~= "Machine Check"; } void main() { writefln("%s", GetMessageText(4)); } This makes sure that outside code cannot change the text of any message, and makes it easy to expand the list of messages in future. Also, no pointers involved. -- Derek Melbourne, Australia

Thanks Derek, but unfortunately I can't use the standard libs... I have to implement the std lib myself... Writing a toy OO kernel for a prog. class project.

?HUH? What std lib? I just used the writefln() to debug this snippet. You don't have use it. However, after seeing Kris' version, I'd go with his. Much neater than mine. ;-) -- Derek Melbourne, Australia 25/02/2005 9:17:08 AM
Feb 24 2005
prev sibling next sibling parent Kris <Kris_member pathlink.com> writes:
In article <1el83535hd3ja$.xafk5jfa77v5$.dlg 40tude.net>, Derek says...
On Thu, 24 Feb 2005 20:16:07 +0000 (UTC), Ron wrote:

[snip]
 The code looks like this:

Or maybe ... import std.stdio; private char[][] exception_messages; char[] GetMessageText(int id) { if (id >= 0 && id < exception_messages.length) return exception_messages[id].dup; else return ""; } static this() { exception_messages ~= "Division By Zero"; exception_messages ~= "Debug"; exception_messages ~= "Non Maskable Interrupt"; exception_messages ~= "Breakpoint"; exception_messages ~= "Into Detected Overflow"; exception_messages ~= "Out of Bounds"; exception_messages ~= "Invalid Opcode"; exception_messages ~= "No Coprocessor"; exception_messages ~= "Double Fault"; exception_messages ~= "Coprocessor Segment Overrun"; exception_messages ~= "Bad TSS"; exception_messages ~= "Segment Not Present"; exception_messages ~= "Stack Fault"; exception_messages ~= "General Protection Fault"; exception_messages ~= "Page Fault"; exception_messages ~= "Unknown Interrupt"; exception_messages ~= "Coprocessor Fault"; exception_messages ~= "Alignment Check"; exception_messages ~= "Machine Check"; } void main() { writefln("%s", GetMessageText(4)); } This makes sure that outside code cannot change the text of any message, and makes it easy to expand the list of messages in future. Also, no pointers involved.

This is why we want to see a compiler-enforced 'readonly' attribute for content ~ to enforce CoW :) That aside -- you can also do this, Ron: struct Msg {int id; char[] text;} static const Msg[] = [ {0, "Division By Zero"}, {1, "Debug"}, {2, "Non Maskable Interrupt"}, {3, "Breakpoint"}, {4, "Into Detected Overflow"}, {5, "Out of Bounds"}, ]; - Kris
Feb 24 2005
prev sibling parent Chris Sauls <ibisbasenji gmail.com> writes:
Assuming these are /static/ values, you could also just do:

private static const char[][] exception_messages = [
	"Division By Zero",
	"Debug",
	"Non Maskable Interrupt",
	"Breakpoint",
	"Into Detected Overflow",
	"Out of Bounds",
	"Invalid Opcode",
	"No Coprocessor",
	"Double Fault",
	"Coprocessor Segment Overrun",
	"Bad TSS",
	"Segment Not Present",
	"Stack Fault",
	"General Protection Fault",
	"Page Fault",
	"Unknown Interrupt",
	"Coprocessor Fault",
	"Alignment Check",
	"Machine Check"
];

-- Chris S
Feb 24 2005
prev sibling next sibling parent =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Ron wrote:
 The C way of:
 
 void[16] *routines = {
 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0
 };
 
 does NOT work. I get the message:
 "Error: a struct is not a valid initializer for a void[16]*"

D uses [ ] instead of { }, for initializing arrays. See http://www.digitalmars.com/d/arrays.html However, it only allows it for *static* arrays. You can also set things at runtime, if you like. --anders
Feb 22 2005
prev sibling next sibling parent Kris <Kris_member pathlink.com> writes:
In article <cvhaar$31av$1 digitaldaemon.com>, Ron says...
The C way of:

void[16] *routines = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};

does NOT work. I get the message:
"Error: a struct is not a valid initializer for a void[16]*"

Same thing with a char array (same way, just w/ string data), but the error
message is:
"Error: a struct is not a valid initializer for a char[32]*"

How do you init these arrays?

First, D uses square brackets to init arrays: # int[] x = [1, 2, 3, 4, 5, 6]; When assigning structs, do it like so: # struct Foo {int a; char[] b;} # Foo[] foo = [{1, "one"}, {2, "two"}]; And so on. There are a number of things that cannot be initialized in this manner (yet). - Kris
Feb 22 2005
prev sibling parent Dave <Dave_member pathlink.com> writes:
This should work for what I believe you were trying to do:

void*[16] routines = [
null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null
];

or

void *routines[16] = [
null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null
];

'[.,.,.]' is for arrays, '{.,.,.}' is for structs.

See: http://digitalmars.com/d/arrays.html for more info. on the syntax for
arrays, arrays of ptrs, ptrs to arrays (like you actually had), init. of arrays,
etc.

- Dave

In article <cvhaar$31av$1 digitaldaemon.com>, Ron says...
The C way of:

void[16] *routines = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};

does NOT work. I get the message:
"Error: a struct is not a valid initializer for a void[16]*"

Same thing with a char array (same way, just w/ string data), but the error
message is:
"Error: a struct is not a valid initializer for a char[32]*"

How do you init these arrays?

--Ron

Feb 24 2005