We need to define the semantics of block initialization of arrays
Don
turnyourkidsintocash at nospam.com
Mon Jun 3 02:06:22 PDT 2013
DMD has always accepted this initializer syntax for static arrays:
float [50] x = 1.0;
If this declaration happens inside a function, or in global
scope, the compiler sets all members of x to 1.0. That is, it's
the same as:
float [50] x = void;
x[] = 1.0;
In my DMD pull requests, I've called this 'block initialization',
since there was no standard name for it.
A lot of code relies on this behaviour, but the spec doesn't
mention it!!!
The problem is not simply that this is unspecified. A long time
ago, if this same declaration was a member of a struct
declaration, the behaviour was completely different. It used to
set x[0] to 1.0, and leave the others at float.init. I'll call
this "first-element-initialization", and it still applies in many
cases, for example when you use a struct static initializer. Ie,
it's the same as:
float [50] x;
x[0] = 1.0;
Note however that this part of the compiler has historically been
very bug-prone, and the behaviour has changed several times.
I didn't know about first-element-initialization when I
originally did the CTFE code, so when CTFE is involved, it always
does block initialization instead.
Internally, the compiler has two functions, defaultInit() and
defaultInitLiteral(). The first does first-element-init, the
second does block-init.
There are several other situations which do block initialization
(not just CTFE). There are a greater number of situations where
first-init can happen, but the most frequently encountered
situations use block-init. There are even some foul cases, like
bug 10198, where due to a bug in CTFE, you currently get a
bizarre mix of both first-init and block-init!
So, we have a curious mix of the two behaviours. Which way is
correct?
Personally I'd like to just use block-init everywhere. I
personally find first-element-init rather unexpected, but maybe
that's just me. I don't know when it would be useful. But
regardless, we need to get this sorted out.
It's a blocker for my CTFE work.
Here's an example of some of the oddities:
----
struct S {
int [3] x;
}
struct T {
int [3] x = 8;
}
struct U {
int [3][3] y;
}
void main()
{
int [3][4] w = 7;
assert( w[2][2] == 7); // Passes, it was block-initialized
S s = { 8 }; // OK, struct static initializer.
first-element-init
S r = S( 8 ); // OK, struct literal, block-init.
T t; // Default initialized, block-init
assert( s.x[2] == 8); // Fails; it was
first-element-initialized
assert( r.x[2] == 8); // Passes; all elements are 8.
Block-init.
assert( t.x[2] == 8); // Passes; all elements are 8.
Block-init.
U u = { 9 }; // Does not compile
// Error: cannot implicitly convert expression (9) of type int
to int[3LU][3LU]
}
---
More information about the Digitalmars-d
mailing list