3 ms·
I'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 thing
by repsilat 15y ago
I'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...