3 ms·
how do you even have VLAs where the array is the non-terminal field? do you embed the size of the array in the type definition or in the structure?
by benmmurphy 9y ago
how do you even have VLAs where the array is the non-terminal field? do you embed the size of the array in the type definition or in the structure?
- unwind 9y agoIt's weird. As far as I can tell, GCC's documentation[1] clearly states: Flexible array members may only appear as the last member of a struct that is otherwise non-empty. What is the article referring to, then? 1: https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Zero-Length.html#Zero-Length https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Zero-Length.htm...
- jwilk 9y agoflexible array member ≠ variable-length array See: https://news.ycombinator.com/item?id=15303211 https://news.ycombinator.com/item?id=15303211
- marcoperaza 9y agoIt has to be in the definition since it is a VLA, not a flexible array member. Accessing the VLAs or members after/between them will generate an offset based on whatever values were used to define the length of the VLAs, so the definition needs to be in scope. Seems like the use case is for struct types defined within a function and used only within that same function execution, or perhaps also accessed through another execution of that same function that results in the exact same definition. In the latter case, you would need to cast the memory to void* for storage between executions, and then back to the regenerated type, since you can only reference types within the scope that they are defined. Weird, but I can see the potential utility when you're optimizing for locality in heap allocations, since the allocator will give you a single contiguous memory block with all of the VLAs, while making several allocations for multiple VLAs could very well return disjoint memory ranges. And then there's the aesthetic utility of behaving like objects in higher-level languages, where having multiple variable-length arrays within an object is standard. See https://stackoverflow.com/questions/14629504/variable-length-array-in-the-middle-of-struct-why-this-c-code-is-valid-for-gcc https://stackoverflow.com/questions/14629504/variable-length... and linked pages.
- wahern 9y agoThis would be a really useful feature in C if it was made more general, even if the scope of the definition remained limited. But with GCC 7 struct { int arr[n]; } s = { 0 }; gives error: variable-sized object may not be initialized And (struct { int arr[n]; }){ 0 } gives error: compound literal has variable size GCC still doesn't even permit a simpler compound literal like (int[n]){ 0 }. I understand that compound literals and VLAs are distinct, and that the above limitations are, strictly speaking, consistent with the standard constructs. But I would think that once you have variable-length struct members that it wouldn't be too difficult to unify the semantics of VLAs and compound literals. If GCC can't be bothered to improve language consistency, then that's pretty strong evidence that VLA struct members are a dead-end and I can't fault clang for avoiding it. But if GCC did improve consistency, it might significantly help push C toward safer array semantics. The last hurdle would be definition scope and working out how declarations worked. Presumably the ABI would require fat pointers that embed VLA annotations. Getting there would be a long, winding road, but this is how it would happen. It's complex, but the cost+benefit ratio would, I think, be better for both compiler writer and programmer compared to the complexity of C++.
- scatters 9y agoYou're thinking of flexible or zero-length array members (`int[]` as the terminal field, or mostly equivalently, where supported, `int[0]`). VLAs in a struct only really make sense for a local type i.e. a struct defined and used within a function: void foo (int n) { struct S { int x[n]; }; } https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
- benmmurphy 9y agothanks. that makes sense. #include <stdio.h> void foo (int n) { struct S { int x[n]; int y; }; printf("offset: %ld\n", __builtin_offsetof(struct S, y)); } int main() { foo(2); foo(16); } offset: 8 offset: 64
- KenoFischer 9y agoIt's about whether you can put stack allocated VLAs into temporary structs: keno@anubis:~$ cat test2.c void bar(int *); int foo(int n) { struct { int non_terminal_val[n]; int some_other_member; } val; bar(val.non_terminal_val); return val.some_other_member; } keno@anubis:~$ gcc -c test2.c keno@anubis:~$ clang test2.c test2.c:4:13: error: fields must have a constant size: 'variable length array in structure' extension will never be supported int non_terminal_val[n]; ^ 1 error generated.
- gjem97 9y ago"will never be supported" I wonder how many times you have to be asked before you put that in the error message.