Anonymous functions using GCC statement expressions

后端 未结 4 1710
感情败类
感情败类 2020-11-29 20:07

This question isn\'t terribly specific; it\'s really for my own C enrichment and I hope others can find it useful as well.

Disclaimer: I know many w

相关标签:
4条回答
  • 2020-11-29 20:53

    This declaration (at block scope):

    int (*max)(int, int) =
        ({
        int __fn__ (int x, int y) { return x > y ? x : y; }
        __fn__;
        });
    

    is not C but is valid GNU C.

    It makes use of two gcc extensions:

    1. nested functions
    2. statement expressions

    Both nested functions (defining a function inside a compound statement) and statement expressions (({}), basically a block that yields a value) are not permitted in C and come from GNU C.

    In a statement expression, the last expression statement is the value of the construct. This is why the nested function __fn__ appears as an expression statement at the end of the statement expression. A function designator (__fn__ in the last expression statement) in a expression is converted to a pointer to a function by the usual conversions. This is the value used to initialize the function pointer max.

    0 讨论(0)
  • 2020-11-29 21:07

    Partial answer: It isn't int(*X) you are interested in. It is int (*X)(y,z). That is a function pointer to the function called X which takes (y,z) and returns int.

    For debugging, this will be really hard. Most debuggers can't trace through a macro. You would most likely have to debug the assembly.

    0 讨论(0)
  • 2020-11-29 21:08

    Your lambda macro exploits two funky features. First it uses nested functions to actually define the body of your function (so your lambda is not really anonymous, it just uses an implicit __fn__ variable (which should be renamed to something else, as double-leading-underscore names are reserved for the compiler, so maybe something like yourapp__fn__ would be better).

    All of this is itself performed within a GCC compound statement (see http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html#Statement-Exprs), the basic format of which goes something like:

    ({ ...; retval; })
    

    the last statement of the compound statement being the address of the just-declared function. Now, int (*max)(int,int) simply gets assigned the value of the compound statement, which is now the pointer to the 'anonymous' function just declared.

    Debugging macros are a royal pain of course.

    As for the reason why test; .. at least here, i get the 'test redeclared as different type of symbol', which I assume means GCC is treating it as a declaration and not a (useless) expression. Because untyped variables default to int and because you have already declared test as a function (essentially, void (*)(void)) you get that.. but I could be wrong about that.

    This is not portable by any stretch of the imagination though.

    0 讨论(0)
  • 2020-11-29 21:13
    1. int (*max)(int, int) is the type of variable you are declaring. It is defined as a function pointer named max which returns int, and takes two ints as parameters.

    2. __fn__ refers to the function name, which in this case is max.

    3. I don't have an answer there. I would imagine you can step through it if you have run it through the preprocessor.

    0 讨论(0)
提交回复
热议问题