digitalmars.D.learn - Does D actually support flexible array members?
- LinguisticMystic (26/26) Aug 18 2022 I'm porting some C code for arena allocator to D, and somehow the
- Krzysztof =?UTF-8?B?SmFqZcWbbmljYQ==?= (32/32) Aug 18 2022 No, D does not support flexible array members or dynamically
- LinguisticMystic (3/4) Aug 18 2022 Okay, got it, thanks.
- Paul Backus (18/39) Aug 18 2022 I think the closest way to approximate this in D is to use a
- IchorDev (3/12) Sep 06 2022 Would Nullable be a good option as well?
- Paul Backus (3/17) Sep 06 2022 For a dynamically-sized struct? No, it would not; Nullable has a
I'm porting some C code for arena allocator to D, and somehow the flexible array members (a feature of C99 for dynamically-sized structs) work in D without significant changes in the code. Here's my arena definition: ``` struct ArenaChunk { size_t size; ArenaChunk* next; char[] memory; // flexible array member } struct Arena { ArenaChunk* firstChunk; ArenaChunk* currChunk; int currInd; } ``` And here's how I use the FAM's memory for allocating stuff: ``` void* result = cast(void*)(&ar.currChunk.memory + ar.currInd); ``` This seems to work, but I'm a little doubtful, does D really support FAMs in the same way as C, or am I misusing some other D feature here? I mean, FAM's aren't even supported by C++, and aren't listed on [the D reference](https://tour.dlang.org/tour/en/basics/arrays) yet somehow the code works.
Aug 18 2022
No, D does not support flexible array members or dynamically sized structs. `char[]` is a D slice, which is NOT equivalent to a C array. A slice is basically a pointer+length pair: ```d // you can't actually name a struct `char[]`, it's just for explanation purposes struct char[] { char* ptr; //pointer to first element size_t length; } ``` Also the allocation code probably only worked by accident and will likely cause memory corruption: ```d void* result = cast(void*)(&ar.currChunk.memory + ar.currInd); ``` `&ar.currChunk.memory` doesn't give you a pointer to the first slice element - it gives you a pointer to the slice itself (the `char[]` "struct"). To get a pointer to the first element you can use `ar.currChunk.memory.ptr`, although since the end goal is to get a pointer to the `ar.currInd` element it's preferable to replace the entire line with this: ```d void* result = &ar.currChunk.memory[ar.currInd]; ``` (this way you get bounds checking on slice indexing so you can't get a pointer past the last element of the slice). Also `void[]` is a more appropriate type for a raw memory array than `char[]` (`char[]` in D is used almost exclusively as "mutable string", and depending on the implementation the garbage collector may not scan `char[]` elements for pointers).
Aug 18 2022
On Thursday, 18 August 2022 at 09:48:48 UTC, Krzysztof Jajeśnica wrote:...Okay, got it, thanks.
Aug 18 2022
On Thursday, 18 August 2022 at 08:41:02 UTC, LinguisticMystic wrote:I'm porting some C code for arena allocator to D, and somehow the flexible array members (a feature of C99 for dynamically-sized structs) work in D without significant changes in the code. Here's my arena definition: ``` struct ArenaChunk { size_t size; ArenaChunk* next; char[] memory; // flexible array member } struct Arena { ArenaChunk* firstChunk; ArenaChunk* currChunk; int currInd; } ``` And here's how I use the FAM's memory for allocating stuff: ``` void* result = cast(void*)(&ar.currChunk.memory + ar.currInd); ```I think the closest way to approximate this in D is to use a zero-length static array: ```d struct ArenaChunk { size_t size; ArenaChunk* next; char[0] memory; } ``` Then your usage example becomes ``` void* result = cast(void*)(ar.currChunk.memory.ptr + ar.currInd); ``` Note that in D you must use `.ptr` to get a pointer to the array's first element; it does not decay automatically like in C.
Aug 18 2022
On Thursday, 18 August 2022 at 11:25:22 UTC, Paul Backus wrote:I think the closest way to approximate this in D is to use a zero-length static array: ```d struct ArenaChunk { size_t size; ArenaChunk* next; char[0] memory; } ```Would Nullable be a good option as well? [https://dlang.org/phobos/std_typecons.html#Nullable](https://dlang.org/phobos/std_typecons.html#Nullable)
Sep 06 2022
On Tuesday, 6 September 2022 at 11:51:35 UTC, IchorDev wrote:On Thursday, 18 August 2022 at 11:25:22 UTC, Paul Backus wrote:For a dynamically-sized struct? No, it would not; Nullable has a fixed size.I think the closest way to approximate this in D is to use a zero-length static array: ```d struct ArenaChunk { size_t size; ArenaChunk* next; char[0] memory; } ```Would Nullable be a good option as well? [https://dlang.org/phobos/std_typecons.html#Nullable](https://dlang.org/phobos/std_typecons.html#Nullable)
Sep 06 2022