我无法完全理解 C 中的 malloc() 函数,更准确地说是在需要使用它时。
当我像这样声明一个指向全局结构的指针时,
struct Position* currentPositionPtr;
我是否需要使用 malloc 为其分配动态内存来初始化它?或者稍后在需要时简单地将结构的指针分配给它是一种好习惯,例如
currentPositionPtr = getPosition();
wheregetPosition()返回指向“struct Position”的指针。
做什么getPosition()?
如果它返回一个指向 的有效指针struct Position,那么您当然不需要为该结构分配内存两次。我希望你的函数看起来不像这样:
struct Position *getPosition()
{
struct Position p = { x, y };
return &p;
}
因为这会表现出未定义的行为(通过返回指向块范围自动对象的指针)。通常,您宁愿返回一个已经 malloc()过时的指针:
struct Position *getPosition()
{
struct Position *p = malloc(sizeof(*p));
p->x = 42;
p->y = 1337;
return p;
}
然后,再次,您不需要额外调用malloc().
但是,如果不是被调用函数负责分配,那么,好吧......调用者是:
void getPosition(struct Position *p)
{
p->x = 42;
p->y = 1337;
}
在后一种情况下,您需要这样称呼它:
struct Position *p = malloc(sizeof(*p));
getPosition(p);
如果你需要你的结构来生存函数返回,或者
struct Position p;
getPosition(&p);
如果你不这样做。
malloc(或其他内存分配功能)在您需要系统为您提供内存时需要。
所以是的,当你这样做时
struct Position* currentPositionPtr;
您将需要致电malloc():
currentPositionPtr = malloc(sizeof(struct Position));
或将指针分配给已分配内存块的地址:
struct Position globalPos;
void func(void) {
struct Position pos;
struct Position* currentPositionPtr = &pos; //ok
struct Position* globalPosPtr = &globalPos; //also ok
...
}
因为您所做的只是声明指针,而不是为结构保留空间。
但是,如果您的指针是global,则将其分配给堆栈分配的内存可能很危险。考虑以下:
struct Position *globalPosPtr = NULL;
void foo(void) {
struct Position pos;
globalPosPtr = &pos;
//can dereference globalPosPtr with no problems here
...
}
void bar(void) {
foo();
//globalPosPtr is invalid here
...
}
至于您关于拥有另一个返回指针的函数的问题:
getPosition()将需要使用malloc或其他一些内存分配函数本身。所以这样做非常好,如果您通常希望将结构中的值初始化为某些值,那么这样做是有意义的。但是,请记住,即使您malloc在其他函数内部调用,free当您完成使用它时也需要内存以防止内存泄漏。
要回答标题中的问题,每当您将某个东西声明为指针时,如果您想使用它,就需要给它一些指向的东西。如果你想让它指向一个新的东西,你需要用malloc()或相关的函数动态分配它。
通常,malloc在以下情况下使用:
有几件简单的事情要理解:
malloc() 只是从堆中返回内存,用户进程有责任通过调用 FREE 系统调用来释放这块内存。
当你在编码时知道,你需要处理固定数量的内存,比如一个结构,一个数组,那么你可以用局部变量和全局变量来满足进程的内存需求。
从您的查询来看,当您必须处理 malloc 并作为结果指针时,您似乎感到困惑。
指针不一定指向 malloc 分配的内存,它可以是任何有效的内存,例如:
int a =2;
int *ptr;
ptr = &a;
所以在这里,ptr 指向不是由 malloc 分配的内存位置。
相反,你可以做
int *ptr;
ptr = (int*)malloc(sizeof(int));
在您的情况下,指向 struct 的指针 currentPositionPtr 可以指向全局/局部变量的地址,前提是内存地址在整个访问该指针的过程中保持有效。
我希望这可以简化事情。
如果您使用的是已知大小的结构,则不必使用 malloc 分配内存,因为内存在不同的结构位置之间是不可更改的,但是,
如果在 struct Position 中,您有一个指向未知大小的指针,具体取决于某些用户输入,那么您可以使用 malloc 来分配所需内存块的大小。
如果你正在分配 struct Position 数组,那么
currentPositionPtr = malloc(sizeof(struct Position)*neededSize);
完成后,您将不得不删除内存
free (currentPositionPtr)
似乎您已经知道 malloc 的工作原理,但我会尝试回答您的问题。
每当您 malloc 时,请确保在其上保留一个指针,以便您可以操纵它(或释放它)。malloc 的优点是它是动态的。您可以声明一个 malloc 结构的链表(例如),而不是声明一个数组,并使用指针来跟踪它们。通过这种方式,您永远不会遇到诸如离开阵列之类的问题。相反,您可以动态地请求更多空间,并在以后需要时释放它。