6 ms·
Case ranges are in gcc for a million years. And also nested functions. I used nested functions a lot but, it was never ported to clang which makes it a bit of a
by buserror 3y ago
Case ranges are in gcc for a million years. And also nested functions. I used nested functions a lot but, it was never ported to clang which makes it a bit of a problem for portability, also, nowadays the linker complains about having to make the stack executable, which is another problem; so I had to stop using them.
I also don't understand why the "C standard" hasn't evolved further -- there was a discussion lately about the committee being out of touch.
Some of these extensions makes life so much easier. Instead we get stupid stuff nobody need, or have been in a header for 200 years (ie, <pthread.h>, whoohoo, I'm delighted this standard header is now a... standard!)
For nested/sub function, it makes so much sense it's not even funny. Having micro-callbacks right there before the call to qsort() (or any other) is SO much better than having to farm out a context, yet-another-static-function etc...
- actionfromafar 3y ago“ Nested functions can even goto back into their parent function, allowing for nonlocal exits to break out of nested functions like Smalltalk blocks, allowing control flow-like functions to be built using them.” Wild! Makes one wonder how something could have evolved if it took C and made it more “functional” and/or smalltalk-ish, without going the dynamic way of ObjectiveC. I don’t exactly love C++ but I find it very useful. Maybe I could have loved that other never conceived C offspring.
- derefr 3y agoNote that this functionality is already in C — in the form of the setjmp/longjmp functions, which indeed allow you to have a parent function that contains "global" error-handling, and then a hierarchy of child functions designed to only be executed from that parent, that can "jump out" to the parent's error handler. (But where "parent" and "child" here are just a conceptual relationship the programmer is keeping track of, not anything the compiler knows about.) The difference is that High C gives you lexically-nested function definitions, thus making labels into things like local variables that have scope + shadowing. And so it becomes sensible — necessary, really, to have a coherent semantics — to extend the (runtime, dynamic) longjmp, into a compile-time-targeted, lexical, syntax-sugared version that jumps to in-scope labels (incl. ones defined outside the current lexically-nested function definition.) If you didn't, then you'd have to decide on what a `goto` to an in-scope but out-of-function label would do instead — compiler error, maybe? — and whatever you choose, it would probably be just as hard to implement as just making it work. (Most of the effort is in extending the CFG to allow some analysis pass to notice that this is happening, after all.)
- flohofwoe 3y ago> I'm delighted this standard header is now a... standard! The POSIX standard isn't the C standard though (for better or worse). Especially on Windows with MSVC "obvious" things like this are traditionally a royal PITA (which also means that a lot of C code coming from the UNIX world simply doesn't build on MSVC even though MSVC is now a decent standard-C compiler again). But yeah, the C standard is just the minimal common subset of what C compilers offer. The good stuff is all in Clang and GCC extensions.
- derefr 3y ago> But yeah, the C standard is just the minimal common subset of what C compilers offer. Why is this? Most other standards — for languages or otherwise — seem to run ahead of implementation, as meetings of major players agreeing on what they'll all implement next, with the standard constraining the implementations on how to do that. But the C standard is seemingly instead just an external, descriptivist report on "what you can get away with writing in C while keeping it completely portable."
- flohofwoe 3y agoDon't know, most likely reason is probably that the C standard was always an afterthought and 'reactive' in the C world (e.g. the language already existed for nearly two decades before the first standard was released). TBH I think the general idea of "let's only standardise what has already been implemented in real world extensions and proven its worth" isn't too bad, especially when looking at the mess that the C++ standard committee made of C++ in the last decade. But even with this pragmatic approach I imagine it's a highly political balancing act to get multiple powerful compiler vendors to actually agree on the same thing. See for instance the C23 auto proposal which contains a special exception for Clang's behaviour which clashes with GCC's behaviour: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3007.htm https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3007.htm
- buserror 3y agoProblem is, that approach forces the committee to roll in stuff from the C++ spec -- stuff that would have been shot in flame if you had hinted about that sort of things as a proposal C extension.. For example the [[keywords]] that had was rolled in because it was already out there -- imagine proposing that out of the blue and see a people self-propel into orbit... On other hand the Case A ... B: syntax that has been out there for 30+ years, well there's a proposal for it but it won't be THAT because well it hasn't been invented here really, we'll make up a different syntax for it instead...
- spacechild1 3y ago> (ie, <pthread.h>, whoohoo, I'm delighted this standard header is now a... standard! <pthreads.h> is POSIX, it has never been - and still don't is! - part of the C standard. In particular, MSVC only supports it through third party libraries. However, C11 added cross-platform thread support with <threads.h>: https://en.cppreference.com/w/c/thread https://en.cppreference.com/w/c/thread. I wouldn't call that "stupid stuff nobody needs".
- trealira 3y ago> and still don't is! "isn't," not "don't is" You're right, though
- spacechild1 3y agod'oh
- uecker 3y agoI agree. Nested functions are very useful often lead to substantially better code. With GCC 14 you can also create heap trampolines, so an executable stack is not required anymore when you take the address of a nested function (if you don't take the address, it isn't required anyway).