digitalmars.D - Minor issue - zero-length fixed size arrays in variable-sized
- Jarrett Billingsley <jarrett.billingsley gmail.com> Jul 08 2009
- bearophile <bearophileHUGS lycos.com> Jul 08 2009
- Tim Matthews <tim.matthews7 gmail.com> Jul 08 2009
- Daniel Keep <daniel.keep.lists gmail.com> Jul 08 2009
- Tim Matthews <tim.matthews7 gmail.com> Jul 08 2009
- Tim Matthews <tim.matthews7 gmail.com> Jul 10 2009
- Jarrett Billingsley <jarrett.billingsley gmail.com> Jul 09 2009
- "Steven Schveighoffer" <schveiguy yahoo.com> Jul 09 2009
- Jarrett Billingsley <jarrett.billingsley gmail.com> Jul 09 2009
- "Steven Schveighoffer" <schveiguy yahoo.com> Jul 10 2009
I noticed in the spec on arrays that "A [fixed-size] array with a dimension of 0 is allowed, but no space is allocated for it. It's useful as the last member of a variable length struct.." This sounds like C99's "flexible array members," where a struct can have an array as its last element that isn't given a size, specifically for allowing variable-sized structs. Well, the issue with a zero-length fixed-size array is that.. uh, you can't access anything out of it. The compiler disallows any indexing of a zero-length array with constant indices, and at runtime, all accesses caught by the array bounds checking. Weirder still, the .ptr of any zero-length array is always null, so you can't even do things like "arr.ptr[5] = x;" (which would be perfectly acceptable in my opinion). Just a silly issue.
Jul 08 2009
Jarrett Billingsley: I have "solved" that problem compiling in release mode...I noticed in the spec on arrays that "A [fixed-size] array with a dimension of 0 is allowed, but no space is allocated for it.
The future most important implementation of D, LDC, allocates a "bit" for it (I have no idea where this bit goes): http://www.dsource.org/projects/ldc/wiki/Docs#Zero-lengthstaticarrays Bye, bearophile
Jul 08 2009
Jarrett Billingsley wrote:I noticed in the spec on arrays that "A [fixed-size] array with a dimension of 0 is allowed, but no space is allocated for it. It's useful as the last member of a variable length struct.." .......
It would be interesting if anyone has yet to find this useful. In c it could be used more directly. In D I think its not much use apart from the offset of property. It would be real bad to have to use it like this: import std.stdio; struct S { int a; uint msgSize; char[0] message; } void setMessage(S* s, const char[] msg) { (cast(char*)(s+S.message.offsetof))[0..s.msgSize] = msg[0..s.msgSize]; } char[] getMessage(S* s) { return (cast(char*)(s+S.message.offsetof))[0..s.msgSize]; } S* createS(uint msgSize) { S* s = cast(S*)((new ubyte[S.sizeof+msgSize]).ptr); s.msgSize = msgSize; return s; } void main() { S* s = createS(5); setMessage(s, "hello"); writeln(getMessage(s)); setMessage(s, "world"); writeln(getMessage(s)); }
Jul 08 2009
You'd have to be mad to use it like that.
struct S
{
int a;
private { size_t size; char[0] data; }
char[] message() { return data.ptr[0..length]; }
size_t length() { return size; }
S* opCall(size_t size)
{
return cast(S*)((new ubyte[S.sizeof+size]).ptr);
}
}
void main()
{
auto s = S(5);
s.message[] = "hello";
writeln(s.message);
s.message[] = "world";
writeln(s.message);
}
Jul 08 2009
Daniel Keep wrote:You'd have to be mad to use it like that.
I am mad.struct S { int a; private { size_t size; char[0] data; } char[] message() { return data.ptr[0..length]; } size_t length() { return size; } S* opCall(size_t size) { return cast(S*)((new ubyte[S.sizeof+size]).ptr); } } void main() { auto s = S(5); s.message[] = "hello"; writeln(s.message); s.message[] = "world"; writeln(s.message); }
I don't know what you'd have to be to use it like that though ^ :)
Jul 08 2009
Steven Schveighoffer wrote:Having the compiler do the right thing is a much better option :) -Steve
Have you reported this issue as a bug/enhancement?
Jul 10 2009
On Thu, Jul 9, 2009 at 2:38 AM, Daniel Keep<daniel.keep.lists gmail.com> wr= ote:You'd have to be mad to use it like that. struct S { =A0 =A0int a; =A0 =A0private { size_t size; char[0] data; } =A0 =A0char[] message() { return data.ptr[0..length]; } =A0 =A0size_t length() { return size; } =A0 =A0S* opCall(size_t size) =A0 =A0{ =A0 =A0 =A0 =A0return cast(S*)((new ubyte[S.sizeof+size]).ptr); =A0 =A0} } void main() { =A0 =A0auto s =3D S(5); =A0 =A0s.message[] =3D "hello"; =A0 =A0writeln(s.message); =A0 =A0s.message[] =3D "world"; =A0 =A0writeln(s.message); }
You can't. The rest of my post explains that T[0].ptr is always null, for some reason. Currently I'm doing almost the same thing, though (cast(char*)(this + 1)[0 .. size]).
Jul 09 2009
On Thu, 09 Jul 2009 09:47:44 -0400, Jarrett Billingsley <jarrett.billingsley gmail.com> wrote:On Thu, Jul 9, 2009 at 2:38 AM, Daniel Keep<daniel.keep.lists gmail.com> wrote:You'd have to be mad to use it like that. struct S { int a; private { size_t size; char[0] data; } char[] message() { return data.ptr[0..length]; }
...
You can't. The rest of my post explains that T[0].ptr is always null, for some reason. Currently I'm doing almost the same thing, though (cast(char*)(this + 1)[0 .. size]).
Would something like this work? (&data)[0..length] -Steve
Jul 09 2009
On Thu, Jul 9, 2009 at 1:09 PM, Steven Schveighoffer<schveiguy yahoo.com> wrote:Would something like this work? (&data)[0..length]
Nope; &data is a char[0]*, and slicing it will get you a char[0][]. Which is pretty useless :D
Jul 09 2009
On Thu, 09 Jul 2009 20:24:16 -0400, Jarrett Billingsley <jarrett.billingsley gmail.com> wrote:On Thu, Jul 9, 2009 at 1:09 PM, Steven Schveighoffer<schveiguy yahoo.com> wrote:Would something like this work? (&data)[0..length]
Nope; &data is a char[0]*, and slicing it will get you a char[0][]. Which is pretty useless :D
d'oh! Yeah, the only improvement I can make on your code then is: (cast(char*)&data)[0..length]; Or the more general: (cast(typeof(data[0])*)&data)[0..length] Which still involves a cast. Crappy. Having the compiler do the right thing is a much better option :) -Steve
Jul 10 2009









bearophile <bearophileHUGS lycos.com> 