The "hackaday" blog focuses on cool things that are typically (but not necessarily) impractical. He isn't suggesting that this "lambda" be used. Instead, this is a stealth blog-post about "__anon", as far as I can tell.<p>Which is really what hackaday is about: finding weird features in hardware/compilers/etc. etc. and using them in some manner. There's a whole lot of obscure features of GCC that are being touched upon in this blogpost (nested functions, whatever is going on with $__anon$, etc. etc.). I can't say that I can figure out exactly what is going on yet, but its kind of exciting to see all of these features get used at once.<p><a href="https://github.com/wd5gnr/clambda/blob/master/clambda2.c" rel="nofollow">https://github.com/wd5gnr/clambda/blob/master/clambda2.c</a><p>EDIT: Unfortunately, it just segfaults for me at the moment.<p><pre><code> $ gcc --std=gnu99 clambda2.c
$ ./a.out
Segmentation fault (core dumped)
$ gcc --version
gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
</code></pre>
This is Ubuntu on Windows, but I doubt that would make a difference.
I'm not conviced that GCC defines the behavior of this, because the trick relies on defining a local function in a block scope, and then allowing it to escape from that block scope:<p><pre><code> {
rettype foo(args ...) { ... }
foo;
}
</code></pre>
GCC local functions are "downward funarg only", as far as I know. This would definitely be wrong:<p><pre><code> {
int local = 42;
rettype foo(args ...) { ... reference local ... }
foo;
}
</code></pre>
then, when <i>foo</i> is called, <i>local</i> no longer exists, which is bad news. The lambda macro doesn't do this (the block doesn't extend the enviornment; nothing is captured from there), and so maybe works by fluke.<p>Another thing to is that pointers to GCC local functions work via trampolines: pieces of executable machine code installed into the stack. When you use GCC functions, the linker has to mark the executable with a bit which says "allow stacks to be executable". The default in most distros is non-executable stacks, which guards against stack overflow exploits.<p>(Speaking of trampolines, I'm not sure about the effective scope of those. If we lift a pointer to a local function inside a block, requiring a trampoline, and then that block terminates, is that trampoline scoped to the block or the function? If it's scoped to the function, won't it be overwritten if we execute that logic multiple times? If the trampoline is scoped to the block, then the invocation of foo is using an out-of-scope trampoline.
So, this doesn't work because the scope of the statement-expression <i>is</i> the scope of the local function, so to use the function outside that scope (as TFA shows) is UB.<p>C w/ GCC's local functions extensions is just not enough for lambda expressions. You have to declare the local function earlier than (and in scope of) the use site.<p>For example, an expression like this:<p><pre><code> float x = add_fns(1,
lambda(float,(float x),{ return 2*x; }),
lambda(float,(float x),{ return 3*x; }));
</code></pre>
may well assign 6.0 to x rather than 5.0 because the first lambda gets overwritten on the stack with the second. That's if it works at all -- after all, we have UB here, and this could just summon cthulhu or anything else.
Apparently the author forgot to look into clang blocks language extension.<p><a href="https://clang.llvm.org/docs/BlockLanguageSpec.html" rel="nofollow">https://clang.llvm.org/docs/BlockLanguageSpec.html</a>
There are a variety of ways to use lambdas in C, each uniquely horrifying.<p><a href="https://codegolf.stackexchange.com/questions/2203/tips-for-golfing-in-c/104999#104999" rel="nofollow">https://codegolf.stackexchange.com/questions/2203/tips-for-g...</a>
I still wonder why C still does’t have lambas implemented by standard. I understand its a quite slow moving language but it would make programming in it mich nicer (see C++11)<p>Are there anh underlying ‘issues’ with lambdas, I wonder?
> However, it seems like if it compiles it ought to work and — mostly — it does.<p>I'm taking this out of context of course but that looks like a very dangerous assumption to make...