digitalmars.D.learn - Avoid initializing a struct field.
- jerro (10/10) May 04 2013 Is there a way to avoid default initializing a struct field in D?
- bearophile (45/52) May 04 2013 I think it's supposed to work. If it doesn't work, then I think
- jerro (37/39) May 04 2013 I was using this code:
- Marco Leise (18/22) May 05 2013 Zero is the magic number. A struct with only binary zeros goes
- Steven Schveighoffer (8/18) May 06 2013 Foo.init must exist, and be filled with *something*. Is it useful to
- jerro (16/35) May 06 2013 I don't care what it contains, I just want to avoid
- Steven Schveighoffer (7/13) May 06 2013 The issue is that bar int in there. The compiler does not generate
Is there a way to avoid default initializing a struct field in D? The following doesn't seem to work: struct Foo { int[42] buffer = void; int bar; } I know I can do this: Foo foo = void But then all fields are uninitialized.
May 04 2013
On Saturday, 4 May 2013 at 18:11:03 UTC, jerro wrote:Is there a way to avoid default initializing a struct field in D? The following doesn't seem to work: struct Foo { int[42] buffer = void; int bar; }I think it's supposed to work. If it doesn't work, then I think it's a compiler bug. What code have you used to test it, and what is the result you have seen? With this code: struct Foo { int[42] buffer; int bar; } int main() { Foo f; return f.bar; } DMD gives this code if I use void and if I don't use it: // With void: Dmain: sub ESP, 0ACh mov ECX, 02Bh push ESI mov ESI, offset FLAT:_D4temp3Foo6__initZ push EDI lea EDI, 8[ESP] rep movsd mov EAX, 0B0h[ESP] pop EDI pop ESI add ESP, 0ACh ret // Without void: Dmain: sub ESP, 0ACh mov ECX, 02Bh xor EAX, EAX push EDI lea EDI, 4[ESP] rep stosd mov EAX, 0ACh[ESP] pop EDI add ESP, 0ACh ret Bye, bearophile
May 04 2013
What code have you used to test it, and what is the result you have seen?I was using this code: extern(C) void foo(Foo* r) { Foo tmp; *r = tmp; } And here is the generated assembly (when using "= void"): push %rbp mov %rsp,%rbp sub $0xc0,%rsp mov %rdi,-0x10(%rbp) movabs $0x65a360,%rsi lea -0xc0(%rbp),%rdi mov $0x15,%ecx rep movsq %ds:(%rsi),%es:(%rdi) movsb %ds:(%rsi),%es:(%rdi) movsb %ds:(%rsi),%es:(%rdi) movsb %ds:(%rsi),%es:(%rdi) movsb %ds:(%rsi),%es:(%rdi) lea -0xc0(%rbp),%rsi mov -0x10(%rbp),%rdi mov $0x15,%cl rep movsq %ds:(%rsi),%es:(%rdi) movsb %ds:(%rsi),%es:(%rdi) movsb %ds:(%rsi),%es:(%rdi) movsb %ds:(%rsi),%es:(%rdi) movsb %ds:(%rsi),%es:(%rdi) leaveq retq The problem here is that the code copies the entire object from some static address instead of just the fields that need to be initialized, and that can be a performance problem. The same is true for your void version. I tried using float[42] instead of int[42] and found out that buffer actually isn't initialized to its default initializer if I use "= void" (the numbers were all 0 instead of NaN), but the performance cost is still there.
May 04 2013
Am Sat, 04 May 2013 21:00:17 +0200 schrieb "jerro" <a a.com>:I tried using float[42] instead of int[42] and found out that buffer actually isn't initialized to its default initializer if I use "= void" (the numbers were all 0 instead of NaN), but the performance cost is still there.Zero is the magic number. A struct with only binary zeros goes to the BS section in the executable (on Windows*), taking up no file space. So it serves a purpose as is. The .init property is a key part of the language. It is used in equality comparisons as well as a template that you can create carbon copies of. "T.init" might be the default value for a parameter of templated function, or it could be used as the initial value for new entries in a list/table with code relying on it being a constant. Your point is valid to some extent, but while logical it adds complexity and increases the odds that someone doesn't expect .init to be a _random_ value. Because that's what it is to templated code that is instantiated with such a struct. *) http://d.puremagic.com/issues/show_bug.cgi?id=7319 -- Marco
May 05 2013
On Sat, 04 May 2013 14:11:02 -0400, jerro <a a.com> wrote:Is there a way to avoid default initializing a struct field in D? The following doesn't seem to work: struct Foo { int[42] buffer = void; int bar; } I know I can do this: Foo foo = void But then all fields are uninitialized.Foo.init must exist, and be filled with *something*. Is it useful to FORCE buffer to not have 0 values? Or is it that you don't care what it has? In the latter, is it terrible that it's 0? I tend to think that without the bar there, it could potentially be uninitialized (not sure if this is the case). But as long as it's there, buffer must also be initialized. -Steve
May 06 2013
On Monday, 6 May 2013 at 15:15:47 UTC, Steven Schveighoffer wrote:On Sat, 04 May 2013 14:11:02 -0400, jerro <a a.com> wrote:I don't care what it contains, I just want to avoid initialization for performance reasons. I have something like this: struct Foo(size_t maxNItems) { Item[maxNItems] buffer; size_t nItems; size_t addItem(...){ ... } void processItems(...){...} } The user of Foo can add up to maxNItems items and then run some algorithm on them. Now say that Foo needs to support up to, say, a thousand items, but in most cases just a few of them will be added. In this case default initialization can take way more time than the actual algorithm.Is there a way to avoid default initializing a struct field in D? The following doesn't seem to work: struct Foo { int[42] buffer = void; int bar; } I know I can do this: Foo foo = void But then all fields are uninitialized.Foo.init must exist, and be filled with *something*. Is it useful to FORCE buffer to not have 0 values? Or is it that you don't care what it has? In the latter, is it terrible that it's 0?
May 06 2013
On Mon, 06 May 2013 15:01:42 -0400, jerro <a a.com> wrote:On Monday, 6 May 2013 at 15:15:47 UTC, Steven Schveighoffer wrote:The issue is that bar int in there. The compiler does not generate initialization code that sets up specific members. It basically has an init value, and it memcpy's that thing onto any uninitialized struct. If you want performance, initialize the memory (all of it) yourself. You can't do any worse :) -SteveFoo.init must exist, and be filled with *something*. Is it useful to FORCE buffer to not have 0 values? Or is it that you don't care what it has? In the latter, is it terrible that it's 0?I don't care what it contains, I just want to avoid initialization for performance reasons.
May 06 2013