匿名函数返回动态分配的值

2023-12-30

该问题基于一种设计模式解决方案,该解决方案可以在其他语言中轻松实现,但在 C 语言中很难实现。缩小范围的代码如下。

建立在这个答案 https://stackoverflow.com/questions/10405436/anonymous-functions-using-gcc-statement-expressions,我正在尝试为匿名函数中动态生成的值找到解决方案。

摘录自答案:

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

静态库代码

struct Super{
}

void add(struct Super *(*superRef)()) {
    // cache the reference (in some linked list)

    // later at some point when an event occurs.
    struct Super *super = superRef(); // instantiate and use it.
}

链接的客户端代码:图书馆代码的用户

struct Sub{
     struct Super *super;
}

add(({
    struct Sub __fn__() { return malloc(sizeof(struct Sub)); } // error
    __fn__;
}));

Error:

error: passing 'void' to parameter of incompatible type 'struct Sub *(*)()

根据澄清请求,请考虑静态库文件中接收对结构对象(未实例化)的引用的接收函数。该库从客户端代码接收该对象。

其次,客户端或静态库不会立即实例化接收到的结构引用。稍后,当系统中有通知时,将调用结构引用来实例化并执行其余的内容。

我再说一遍,具体要求是保存对库用户(客户端代码)传递的结构的非实例化引用。

Summary

基本上,一个 Runner 接收指向多态工厂方法的指针,该方法会缓存并稍后在事件发生时调用以实例化并执行。


正确的顺序是:

  1. learn C
  2. do magic

反之则行不通。({})不会为你扭曲语义。如果你的add需要一个返回的函数struct Super*,它不能与struct Sub,即使你把缺失的*那里。

这仅适用于教程点 https://www.tutorialspoint.com/compile_c99_online.php:

#include <stdio.h>
#include <stdlib.h>

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;
}

创建了一个小型库项目,其中嵌入了匿名魔法和堆分配中的匿名魔法。它没有多大意义,但它有效:

测试库.h

#ifndef TESTLIB_H_
#define TESTLIB_H_

struct Testruct{
    const char *message;
    void (*printmessage)(const char *message);
};

extern struct Testruct *(*nonsense())();

#endif

测试库.c

#include "testlib.h"
#include <stdio.h>
#include <stdlib.h>

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 <stdio.h>
#include <stdlib.h>

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;
}

我按照以下步骤操作https://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html https://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html用于构建和运行它(实际上 3 个 gcc 调用:gcc -c -Wall -Werror -fpic testlib.c, gcc -shared -o libtestlib.so testlib.o, gcc -L. -Wall -o test test.c -ltestlib和一些战斗LD_LIBRARY_PATH)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

匿名函数返回动态分配的值 的相关文章

随机推荐