4 ms·
If you put basic standard compliance aside, it also strips down the errors from arguable code to horrifying coding practice. http://clang.debian.net/status.php
by valisystem 15y ago
If you put basic standard compliance aside, it also strips down the errors from arguable code to horrifying coding practice.
http://clang.debian.net/status.php?version=3.0&key=VARIABLE_LENGTH_ARRAY http://clang.debian.net/status.php?version=3.0&key=VARIA...
http://clang.debian.net/status.php?version=3.0&key=NON-POD http://clang.debian.net/status.php?version=3.0&key=NON-P...
- newman314 15y agoWhat could be nice is if the error pages could suggest possible fixes for the errors that have "will never support". Might be helpful to guide bug-fixers (esp. ones that are starting out).
- viraptor 15y agoThere's a clickable text on the top of those pages that points at the clang FAQ fragment suggesting possible fixes.
- aidenn0 15y agoReally I never got the argument for disallowing variable-length arrays at the end of a C structure. I completely agree with disallowing non-PoD variable-length arrays as well as variable-length arrays in the middle of a structure though.
- nknight 15y agoThe entire concept of variable-length C arrays is at best iffy, but including them in structs is pretty crazy. Consider these two questions: 1) What is the sizeof a struct containing a variable-length array? 2) How do you create an array of structs containing variable-length arrays?
- ori_b 15y ago1) The sum of sizes of the padding and fixed-size members of the struct. In the context of C, this is expected and fairly sane. It also matches the C89 idiom of ending a struct intended with a single element array when you want a variable length array. If C allowed zero-element arrays, then they would be used. /* c89 */ struct { int len; int vla[1]; /* really len elements long */ } MyVLAStruct; 2) Carefully.
- nknight 15y ago> 2) Carefully. Can you provide code demonstrating how you will "carefully" create a C array of structs with a variable-sized member? It will be very educational for me, at least, and I think others, as well.
- ori_b 15y agoWell, in the normal case, you wouldn't do it. These variable length structures need to be created on the heap to be able to be used in a variable length way, for the most part, so you'd just put a pointer to them into an array. However, I can think of a couple of methods, such as packing into an array, and using a second one to index it, like so: a = [aaaa,bb,ccc,dd] idx = [0,4,6,9] To get to the i'th element of a, accesses would go through idx like so: a[idx[i]]. In general, of course, there's no way to allow O(1) access and updates without occasional repacking.
- nknight 15y agoThis is exactly the problem I'm getting at, you're not actually working within the confines of C here, you're creating funny workarounds for the fact that certain C features don't work how you want them to, and you're violating the type system in the process. The concept of VLAs does not fit the language well, they're inherently something of an anomaly. Allowing them in structs would simply multiply the anomalies. I'm frankly shocked that they were codified in C99 at all, rather than codifying something akin to alloca() with implementation-defined behavior, but I'm infinitely grateful the committee did not elect to make them anything more than they are -- which is a semi-portable mechanism for allocating arbitrary amounts of automatic memory.
- cygx 15y agoVLAs at the end of C structures could have been allowed. However, if you read the standard, you'll realize that it would have involved specifying far more exceptional cases than the mostly equivalent solution via flexible array members (ie allowing the last member to have incomplete array type).
- repsilat 15y agoI'm not altogether sure about VLAs' place in C itself, but they (along with contiguous storage of heterogeneous data) are neat ideas that let you do a few things cleverly. I think the usual example is a linked list of strings. Done the "normal" way each string will cause two cache misses - one for the string data, and one for the list node. If you're super unlucky you might get three cache misses (one for the node, one for the string object, one for the string data...). Done this way you only get one cache miss, which is pretty good and better than any other language will give you. Another few cool things: If elements "know about themselves" (have a size element or a vtable etc etc) you can make stacks and queues without the need for a separate index. There are also a few things you can probably only do in ASM: Say you have an "array" of objects "inheriting" from a common base (with sizes depending on their type) and all you ever want to do with them is iterate over them calling virtual functions on them. A nice way to do it would be to keep the iteration logic at the end of the virtual functions (which know about the sizes of their respective objects) and do something that smells a little like tail-call-elimination, maybe with a sentinel object on the end to wrap things up nicely. To get the best bang for your buck you'd need an architecture that isn't preachy about the stack or calling conventions, of course, but it still might be worth doing for a laugh. Erm, I guess this wasn't too clear. In some pseudocode below: virtual void Factorial::process_and_print() { //processing logic: this->n *= (++this->i); print(this->n); //iteration logic: this += sizeof(Factorial); this->process(); //must do TCO } virtual void Message::process_and_print() { //processing logic: print(this->message); //iteration logic: this += sizeof(Message);//message stored by pointer this->process(); } virtual void Sentinel::process() { //iteration logic: return; } funnyArray<Processable> fa; fa.add(Factorial(1)); fa.add(Message("hello")); fa.add(Sentinel()); fa.run(process); //prints something like "1hello" I guess you'd mostly want the iteration logic and the sentinel to be taken care of by the language/library, too, but that's probably not worth thinking about unless there's actually a real use-case for something like this...