Anonymous functions return dynamically allocated values

前端 未结 4 1954
北恋
北恋 2021-01-29 06:12

The question is based on a design pattern solution easily doable in other languages but difficult to implement in C. The narrowed down code is below.

Building on this an

4条回答
  •  走了就别回头了
    2021-01-29 06:15

    The correct order is:

    1. learn C
    2. do magic

    It just will not work in the other way. ({}) does not bend the semantics for you. If your add expects a function which returns struct Super*, it will not work with struct Sub, not even if you put the missing * there.

    This just works on TutorialsPoint:

    #include 
    #include 
    
    int max(int a,int b){
        if(a>b)
            return a;
        return b;
    }
    
    struct Super{};
    
    void add(struct Super *(*superRef)()) {
        struct Super *(*secretStorage)()=superRef;
        /* ... */
        struct Super *super = secretStorage();
        /* ... */
        free(super);
        printf("Stillalive\n");
    }
    
    int main()
    {
        printf("Hello, World!\n");
    
        int (*myMax)(int,int); // <-- that is a function pointer
    
        myMax=max;             // <-- set with oldschool function
        printf("%d\n",myMax(1,2));
    
        myMax = ({             // <-- set with fancy magic
            int __fn__ (int x, int y) { return x < y ? x : y; }
            __fn__;
        });    
        printf("%d - intentionally wrong\n",myMax(1,2));
    
        add(
            ({
                struct Super* fn(){
                    printf("Iamhere\n");
                    return malloc(sizeof(struct Super));
                }
                fn;}));
        printf("Byfornow\n");
        return 0;
    }
    

    Created a small library project with anonymous magic embedded in anonymous magic and heap allocation. It does not make much sense, but it works:

    testlib.h

    #ifndef TESTLIB_H_
    #define TESTLIB_H_
    
    struct Testruct{
        const char *message;
        void (*printmessage)(const char *message);
    };
    
    extern struct Testruct *(*nonsense())();
    
    #endif
    

    testlib.c

    #include "testlib.h"
    #include 
    #include 
    
    const char *HELLO="Hello World\n";
    
    struct Testruct *(*nonsense())(){
        return ({
            struct Testruct *magic(){
                struct Testruct *retval=malloc(sizeof(struct Testruct));
                retval->message=HELLO;
                retval->printmessage=({
                    void magic(const char *message){
                        printf(message);
                    }
                    magic;
                });
                return retval;
            }
            magic;
        });
    }
    

    test.c

    #include "testlib.h"
    #include 
    #include 
    
    int main(){
        struct Testruct *(*factory)()=nonsense();
        printf("Alive\n");
        struct Testruct *stuff=factory();
        printf("Alive\n");
        stuff->printmessage(stuff->message);
        printf("Alive\n");
        free(stuff);
        printf("Alive\n");
        return 0;
    }
    

    I followed the steps in https://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html for building an running it (practically 3 gcc calls: gcc -c -Wall -Werror -fpic testlib.c, gcc -shared -o libtestlib.so testlib.o, gcc -L. -Wall -o test test.c -ltestlib and a bit of fight with LD_LIBRARY_PATH)

提交回复
热议问题