有人可以向我解释一下创建带有和不带有 malloc 的结构之间的区别吗?什么时候应该使用malloc,什么时候应该使用常规初始化?
例如:
struct person {
char* name;
};
struct person p = {.name="apple"};
struct person* p_tr = malloc(sizeof(struct person));
p_tr->name = "apple";
Run Code Online (Sandbox Code Playgroud)
两者之间到底有什么区别?什么时候会使用一种方法而不是其他方法?
具有如下数据结构;
struct myStruct {
int a;
char *b;
};
struct myStruct p; // alternative 1
struct myStruct *q = malloc(sizeof(struct myStruct)); // alternative 2
Run Code Online (Sandbox Code Playgroud)
替代方案 1:在堆栈myStruct上分配一定宽度的内存空间,并将结构体的内存地址返回给您(即,为您提供结构体的第一个字节地址)。如果它是在函数中声明的,则当函数退出时,它的生命结束(即,如果函数超出范围,则无法访问它)。&p
方案2:在堆上分配一个myStruct宽度的内存空间,在栈上分配一个类型为指针宽度的内存空间。堆栈上的指针值被分配结构体的内存地址(位于堆上)的值,并且该指针地址(不是实际的s 地址)将返回给您。在您使用之前,它的生命周期永远不会结束。(struct myStruct*)structfree(q)
在后一种情况下,例如,myStruct位于内存地址0xabcd0000和q位于内存地址0xdddd0000;然后,内存地址上的指针值0xdddd0000被分配为0xabcd0000,并将其返回给您。
printf("%p\n", &p); // will print "0xabcd0000" (the address of struct)
printf("%p\n", q); // will print "0xabcd0000" (the address of struct)
printf("%p\n", &q); // will print "0xdddd0000" (the address of pointer)
Run Code Online (Sandbox Code Playgroud)
解决你的第二部分;何时使用哪个:
malloc它。您可以通过返回指针来使用结构体的值,例如:return q;。malloc内存。用法示例:
struct myStruct {
int a;
char *b;
};
struct myStruct *foo() {
struct myStruct p;
p.a = 5;
return &p; // after this point, it's out of scope; possible warning
}
struct myStruct *bar() {
struct myStruct *q = malloc(sizeof(struct myStruct));
q->a = 5;
return q;
}
int main() {
struct myStruct *pMain = foo();
// memory is allocated in foo. p.a was assigned as '5'.
// a memory address is returned.
// but be careful!!!
// memory is susceptible to be overwritten.
// it is out of your control.
struct myStruct *qMain = bar();
// memory is allocated in bar. q->a was assigned as '5'.
// a memory address is returned.
// memory is *not* susceptible to be overwritten
// until you use 'free(qMain);'
}
Run Code Online (Sandbox Code Playgroud)
如果我们假设这两个示例都发生在函数内部,则:
\n\nstruct person p = {.name="apple"};\nRun Code Online (Sandbox Code Playgroud)\n\nC 实现会p在函数执行结束时自动分配内存并释放内存(或者,如果语句位于函数中嵌套的块内,则在该块执行结束时释放内存)。这在以下情况下很有用:
malloc可能会更好。阈值根据情况而变化。)在:
\n\nstruct person* p_tr = malloc(sizeof(struct person));\np_tr->name = "apple";\nRun Code Online (Sandbox Code Playgroud)\n\n程序显式地为对象请求内存,并且程序通常应该在free处理完该对象后释放该内存。这在以下情况下很有用:
malloc自动对象提供更多的内存用于分配。)请注意,将成员struct person p = {.name="apple"};初始化name为"apple"并将所有其他成员初始化为零。malloc但是,使用和分配的代码p_tr->name不会初始化其他成员。
如果struct person p = {.name="apple"};出现在函数外部,则它将创建一个具有静态存储持续时间的对象。它将在程序执行期间存在。
相反struct person* p_tr = malloc(sizeof(struct person));,最好使用struct person *p_tr = malloc(sizeof *p_tr);. 对于前者,更改p_tr需要在两个地方进行编辑,这使得人类有机会犯错误。对于后者,仅更改一处的类型p_tr仍将导致请求正确的大小。