我正在使用GBDK编写Gameboy ROM,其中有一个不稳定的malloc版本,我无法工作。我也无法在结构中返回结构。这让我试图返回一个指针,这就是为什么我想知道是否有办法避免在返回结构指针时使用malloc?
我基本上想要做的是我希望能够写出这样的东西:
create_struct(struct_name, char member_x, char member_y);
这是我用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;
};
答案 0 :(得分:5)
有各种有效的方法可以返回一个指针(一个结构或任何类型的对象),但是返回一个指向一个新对象的指针的唯一方法并不存在在调用函数之前,使用malloc
,realloc
,calloc
,aligned_alloc
(C11)或某些实现定义的分配函数(例如mmap
on POSIX系统等。)。
您可以返回有效指针的其他方法包括:
指向具有static
存储持续时间的对象的指针。只有这样一个对象的实例存在,所以这通常是一种不好的方式。
作为参数传递给函数的指针,用作存储结果的位置。这通常是一种很好的方法,因为您将获取存储的责任转交给调用者。
指向从某种全局池中获取的对象的指针。对于低端游戏设备,这可能是嵌入式系统和游戏设计中非常好的方法。
答案 1 :(得分:2)
是否可以在不使用malloc的情况下返回指向结构的指针?
予。 从技术上讲,是的。你可以使你的结构static
使其在函数调用中幸存下来:
struct foo *bar()
{
static struct foo f = { 1, 2, 3 };
return &f;
}
但我怀疑你确实想要这样做(因为这有一些有趣的副作用,请阅读static
关键字的含义)。您有几种不同的可能性:
II。 C标准库采用的方法总是使调用者隐含地负责提供结构和管理内存。因此,函数接受指向struct的指针并填充
,而不是返回指针。void dostuff(struct foo *f)
{
foo->quirk = 42;
}
III。或者返回结构本身,它没有伤害,它是否(它甚至可以移动优化):
struct foo bar()
{
struct foo f = { 1, 2, 3 };
return f;
}
所以,选择你的毒药。
答案 2 :(得分:0)
只需执行以下操作:
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;
}
结构需要在其他地方“分配”(可能在堆栈上是你最好的选择)。
答案 3 :(得分:0)
您可以将结构作为参数传递,并让函数初始化它:
struct point *makepoint(struct point *pt, char x, char y) {
pt->x = x;
pt->y = y;
return pt;
}
然后像这样调用它:
struct point pt;
makepoint(&pt, 'a', 'b');
但是你可能只是做了:
struct point pt = { 'a', 'b' };
答案 4 :(得分:0)
请注意,在这种情况下(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;
}
答案 5 :(得分:0)
如果无法修复malloc()
,那么您可能只想管理自己的预分配点,并限制可以“创建”的点数。您需要稍微改变一点以便于管理:
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()
上,而不是在makepoint()
返回的结果上调用free_point_list
。
void unmakepoint (struct point *p) {
union free_point *fp = (union free_point *)p;
if (fp) {
fp->next = free_point_list;
free_point_list = fp;
}
}
答案 6 :(得分:0)
最简单的事情就是返回一个使用命名初始值设定项创建的结构,并在内联函数中执行此操作,以便零开销:
static inline struct point makepoint(char x, char y) {
return (struct point) { .x = x, .y = y };
}
然后你可以这样称呼它:
struct point foo = makepoint(10, 20);
不可能更简单!