[英]Difference in creating a struct using malloc and without malloc
有人可以向我解释使用和不使用 malloc 创建结构之间的区别吗? 什么时候应该使用 malloc,什么时候应该使用常规初始化?
例如:
struct person {
char* name;
};
struct person p = {.name="apple"};
struct person* p_tr = malloc(sizeof(struct person));
p_tr->name = "apple";
两者之间的真正区别是什么? 什么时候会使用一种方法而不是其他方法?
具有像这样的数据结构;
struct myStruct {
int a;
char *b;
};
struct myStruct p; // alternative 1
struct myStruct *q = malloc(sizeof(struct myStruct)); // alternative 2
备选方案 1:在堆栈上分配一个myStruct
宽度的内存空间并将结构的内存地址交还给您(即, &p
为您提供结构的第一个字节地址)。 如果它是在函数中声明的,那么它的生命在函数退出时结束(即,如果函数超出范围,则无法访问它)。
选择2:分配myStruct
宽度对堆内存空间和类型的存储器空间中的指针宽度(struct myStruct*)
上堆叠。 堆栈上的指针值被分配了结构(在堆上)的内存地址的值,并且这个指针地址(不是实际的struct
地址)被交还给你。 在您使用free(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)
解决您的第二部分; 何时使用哪个:
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);'
}
如果我们假设两个例子都出现在一个函数中,那么在:
struct person p = {.name="apple"};
C 实现自动为p
分配内存并在函数执行结束时释放它(或者,如果语句在嵌套在函数中的块内,则当该块的执行结束时)。 这在以下情况下很有用:
malloc
可能更好。阈值因情况而异。)在:
struct person* p_tr = malloc(sizeof(struct person));
p_tr->name = "apple";
该方案明确要求内存对象,程序一般应释放内存, free
当这个对象。 这在以下情况下很有用:
malloc
分配提供的malloc
比为自动对象分配的malloc
多。) 注意struct person p = {.name="apple"};
用"apple"
初始化name
成员并将所有其他成员初始化为零。 但是,使用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
在一个地方更改p_tr
的类型仍然会导致请求正确的大小。
struct person p = {.name="apple"};
^这是为 person 类型的变量/实例自动分配的。
struct person* p_tr = malloc(sizeof(person));
^这是对 person 类型的变量/实例的动态分配。
静态内存分配发生在编译时。 动态内存分配意味着它在程序执行该指令行时在运行时分配内存
根据您的评论判断,您对何时使用其中一个感兴趣。 请注意,所有类型的分配都会保留足以容纳其中变量值的计算机内存。 大小取决于变量的类型。 静态分配的变量由编译器固定到内存中的某个位置。 自动分配的变量由同一个编译器固定到堆栈中的某个位置。 动态分配的变量在程序启动之前不存在,并且在由“malloc”或其他函数分配之前在内存中没有任何位置。
所有命名变量都是静态或自动分配的。 动态变量由程序分配,但为了能够访问它们,仍然需要一个命名变量,它是一个指针。 指针是一个足够大的变量,可以保存另一个变量的地址。 后者可以动态或静态或自动分配。
问题是,如果您的程序不知道在执行期间需要使用的对象数量,该怎么办。 例如,如果您从文件中读取一些数据并在您的程序中创建一个动态结构,如列表或树,该怎么办。 您并不确切知道您将拥有这样一个结构体的成员数量。 这是动态分配变量的主要用途。 您可以根据需要创建任意多个,并将所有内容都放在列表中。 在最简单的情况下,您只需要一个指向列表开头的命名变量即可了解列表中的所有对象。
另一个有趣的用途是当您从函数返回复杂结构时。 如果在栈上自动分配,从函数返回后将不复存在。 动态分配的数据将是持久的,直到它被明确释放。 因此,使用动态分配在这里会有所帮助。
还有其他用途。
在您的简单示例中,两种情况没有太大区别。 第二个需要额外的计算机操作,调用'malloc'函数为你的结构分配内存。 在第一种情况下,结构的内存是否分配在程序启动时定义的静态程序区域中。 请注意,第二种情况下的指针也是静态分配的。 它只保留结构的内存区域的地址。
此外,作为一般规则,动态分配的数据最终应由“free”函数释放。 您无法释放静态数据。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.