关于C#:是否可以在不使用malloc的情况下返回指向结构的指针?

Is it possible to return a pointer to a struct without using malloc?

我正在使用GBDK编写一个Gameboy ROM,它有一个不稳定的malloc版本,我无法工作。我也无法返回结构中的结构。这让我尝试返回一个指针,这就是为什么我想知道是否有一种方法可以避免在返回结构指针时使用malloc?

我基本上想做的是,我希望能够写这样的东西:

1
create_struct(struct_name, char member_x, char member_y);

这是我用malloc编写的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 struct point {
    char member_x;
    char member_y;
};


struct point *makepoint(char member_x, char member_y) {
    struct point *temp = malloc(sizeof(struct point));

    temp->member_x = member_x;
    temp->member_y = member_y;

    return temp;
};


返回指针(指向结构或任何类型的对象)有多种有效方法,但返回指向在调用函数之前不存在的新对象的指针的唯一方法是使用mallocrealloccallocaligned_alloc(c11)或某些实现定义的分配函数(例如posix上的mmap。系统等)。

返回有效指针的其他方法包括:

  • 指向具有static存储持续时间的对象的指针。只有一次这样的对象实例存在,所以这通常是一个坏方法。

  • 作为参数传递给函数的指针,用作存储结果的位置。这通常是一种很好的方法,因为您将获得存储的责任转交给了调用者。

  • 指向从某种全局池中获取的对象的指针。在嵌入式系统和低端游戏设备的游戏设计中,这可能是一种非常好的方法。


  • Is it possible to return a pointer to a struct without using malloc?

    技术上是的。您可以使结构static在函数调用中存活:

    1
    2
    3
    4
    5
    struct foo *bar()
    {
        static struct foo f = { 1, 2, 3 };
        return &f;
    }

    但我怀疑你是否真的想这样做(因为这有有趣的副作用,请阅读static关键字的含义)。您有几种不同的可能性:

    二。C标准库采用的方法总是让调用者隐式地负责提供结构和管理内存。因此,函数不返回指针,而是接受指向结构的指针并填充它:

    1
    2
    3
    4
    void dostuff(struct foo *f)
    {
        foo->quirk = 42;
    }

    iii.或者返回结构本身,它不会伤害,是吗(甚至可以移动优化):

    1
    2
    3
    4
    5
    struct foo bar()
    {
        struct foo f = { 1, 2, 3 };
        return f;
    }

    所以,选择你的毒药。


    最简单的事情就是返回一个使用命名初始值设定项创建的结构,并在内联函数中这样做,这样就没有开销:

    1
    2
    3
    static inline struct point makepoint(char x, char y) {
      return (struct point) { .x = x, .y = y };
    }

    然后你可以这样称呼它:

    1
    struct point foo = makepoint(10, 20);

    再简单不过了!


    如果无法固定malloc(),那么您可能只想管理自己的预分配点数,并限制可以"创建"的点数。为了便于管理,您需要稍微改变您的观点:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    union free_point {
        union free_point *next;
        struct point data;
    };

    union free_point free_point_pool[MAX_POINTS];
    union free_point *free_point_list;

    struct point *makepoint(char member_x, char member_y) {
        static int i;
        union free_point *temp;

        temp = 0;
        if (i == MAX_POINTS) {
            if (free_point_list) {
                temp = free_point_list;
                free_point_list = temp->next;
            }
        } else {
            temp = free_point_pool + i++;
        }

        if (temp) {
            temp->data.x = x;
            temp->data.y = y;
        }

        return &temp->data;
    };

    然后,您应该创建一个新函数,将它放在free_point_list上,而不是对makepoint()返回的结果调用free()

    1
    2
    3
    4
    5
    6
    7
    void unmakepoint (struct point *p) {
        union free_point *fp = (union free_point *)p;
        if (fp) {
            fp->next = free_point_list;
            free_point_list = fp;
        }
    }

    注意,在这种情况下(struct point只占用2个字节),您可以返回struct point而不是struct point *(这不应该用大结构来完成)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #include <stdio.h>

    struct point {
        char member_x;
        char member_y;
    };

    struct point makepoint(char member_x, char member_y)
    {
        struct point temp;

        temp.member_x = member_x;
        temp.member_y = member_y;
        return temp;
    }

    int main(void)
    {
        struct point t = makepoint('a', 'b');

        printf("%c %c
    "
    , t.member_x, t.member_y);
        return 0;
    }

    可以将结构作为参数传递,并让函数初始化它:

    1
    2
    3
    4
    5
    struct point *makepoint(struct point *pt, char x, char y) {
        pt->x = x;
        pt->y = y;
        return pt;
    }

    然后这样称呼它:

    1
    2
    struct point pt;
    makepoint(&pt, 'a', 'b');

    但你也可以这样做:

    1
    struct point pt = { 'a', 'b' };


    只需做如下的事情:

    1
    2
    3
    4
    void makepoint(struct point *dest, char member_x, char member_y) {
         dest->member_x = member_x; // you had these wrong in your code, by the way
         dest->member_y = member_y;
    }

    结构将需要"分配"到其他地方(可能在堆栈上是您的最佳选择)。