简体   繁体   English

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

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

I'm writing a Gameboy ROM using the GBDK, which has an unstable version of malloc that I'm unable to get working. 我正在使用GBDK编写Gameboy ROM,它有一个不稳定的malloc版本,我无法工作。 I'm also unable to return a struct within a struct. 我也无法在结构中返回结构。 That leaves me trying to return a pointer, which is why I'm wondering if there is a way to avoid using malloc when returning a struct pointer? 这让我试图返回一个指针,这就是为什么我想知道是否有办法避免在返回结构指针时使用malloc?

What I'm basically trying to do is that I want to be able to write something like this: 我基本上想要做的是我希望能够写出这样的东西:

create_struct(struct_name, char member_x, char member_y);

This is the code I have written using malloc: 这是我用malloc编写的代码:

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

There are various valid ways to return a pointer (to a struct, or any type of object), but the only way to return a pointer to a new object that didn't exist before the function was called is to use malloc , realloc , calloc , aligned_alloc (C11), or some implementation-defined allocation function (eg mmap on POSIX systems, etc.). 返回指针(到结构或任何类型的对象)有各种有效的方法,但是在调用函数之前返回指向不存在的新对象的指针的唯一方法是使用mallocrealloccallocaligned_alloc (C11)或某些实现定义的分配函数(例如POSIX系统上的mmap等)。

Other ways you could return a valid pointer include: 您可以返回有效指针的其他方法包括:

  1. A pointer to an object with static storage duration. 指向具有static存储持续时间的对象的指针。 Only once instance of such an object exists, so this is usually a bad way. 只有一个这样的对象的实例存在,所以这通常是一个坏方法。

  2. A pointer that was passed to the function as an argument for use as a place to store the result. 作为参数传递给函数的指针,用作存储结果的位置。 This can often be a good approach, since you pass off responsibility for obtaining the storage to the caller. 这通常是一种很好的方法,因为您将获取存储的责任转嫁给调用者。

  3. A pointer to an object obtained from some sort of global pool. 指向从某种全局池中获取的对象的指针。 This could be a very good approach in embedded systems and game design for low-end gaming devices. 对于低端游戏设备,这可能是嵌入式系统和游戏设计中非常好的方法。

Is it possible to return a pointer to a struct without using malloc? 是否可以在不使用malloc的情况下返回指向结构的指针?

I. Technically, yes. I. 技术上,是的。 You can make your struct static so that it survives function calls: 您可以使结构static以便它能够在函数调用中存活:

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

But I doubt you actually want to do this (since this has funny side effects, read up on the meaning of the static keyword). 但我怀疑你真的想这样做 (因为这有很多有趣的副作用,请阅读static关键字的含义)。 You have several different possibilities: 你有几种不同的可能性:

II. II。 The approach what the C standard library takes is always making the caller implicitly responsible for providing the struct and managing memory. C标准库采用的方法总是使调用者隐含地负责提供结构和管理内存。 So instead of returning a pointer, the function accepts a pointer to struct and fills it: 因此,函数接受指向struct的指针并填充它,而不是返回指针:

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

III. III。 Or return the struct itself, it doesn't hurt, does it (it can even be move-optimized): 或者返回结构本身,它不会伤害它,它(它甚至可以移动优化):

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

So, choose your poison. 所以,选择你的毒药。

just do something like: 做一些像:

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

The structure will need to be "allocated" elsewhere (probably on the stack is your best bet). 该结构需要在其他地方“分配”(可能在堆栈上是你最好的选择)。

You could pass the struct as a parameter and have the function initialize it : 您可以将结构作为参数传递,并让函数初始化它:

struct point *makepoint(struct point *pt, char x, char y) {
    pt->x = x;
    pt->y = y;
    return pt;
}

and then call it like this : 然后像这样调用它:

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

but then you might as well just have done : 但是你可能只是做了以下事情:

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

Note that in this case ( struct point only occupies 2 bytes) you can return struct point instead of struct point * , (this should not be done with large structs) 请注意,在这种情况下( struct point只占用2个字节),您可以返回struct point而不是struct point * ,(这不应该使用大型结构)

#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\n", t.member_x, t.member_y);
    return 0;
}

If it is not possible to get malloc() fixed, then you may just want to manage your own pre-allocated points, and limit the number of points that can be "created". 如果无法修复malloc() ,那么您可能只想管理自己的预分配点,并限制可以“创建”的点数。 You would need to alter your points a little to allow for easier management: 您需要稍微改变一点以便于管理:

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

Then, instead of calling free() on the result returned by makepoint() , you should create a new function to place it on the free_point_list . 然后,您应该创建一个新函数将它放在free_point_list上,而不是在makepoint()返回的结果上调用free()

void unmakepoint (struct point *p) {
    union free_point *fp = (union free_point *)p;
    if (fp) {
        fp->next = free_point_list;
        free_point_list = fp;
    }
}

The simplest thing is just to return a structure that has been created using named initializers, and do so in an inline function, so that there is zero overhead: 最简单的方法就是返回一个使用命名初始值设定项创建的结构,并在内联函数中执行此操作,以便零开销:

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

Then you can call it like this: 然后你可以像这样调用它:

struct point foo = makepoint(10, 20);

Couldn't be simpler! 不能简单!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM