简体   繁体   English

使用 malloc 和不使用 malloc 创建结构体的区别

[英]Difference in creating a struct using malloc and without malloc

Could someone please explain to me the difference between creating a structure with and without malloc.有人可以向我解释使用和不使用 malloc 创建结构之间的区别吗? When should malloc be used and when should the regular initialization be used?什么时候应该使用 malloc,什么时候应该使用常规初始化?

For example:例如:

struct person {

    char* name;

};

struct person p = {.name="apple"};

struct person* p_tr = malloc(sizeof(struct person));
p_tr->name = "apple";

What is really the difference between the two?两者之间的真正区别是什么? When would one approach be used over others?什么时候会使用一种方法而不是其他方法?

Having a data structure like;具有像这样的数据结构;

struct myStruct {
    int a;
    char *b;
};

struct myStruct p;  // alternative 1
struct myStruct *q = malloc(sizeof(struct myStruct));  // alternative 2
  • Alternative 1: Allocates a myStruct width of memory space on stack and hands back to you the memory address of the struct (ie, &p gives you the first byte address of the struct).备选方案 1:在堆栈上分配一个myStruct宽度的内存空间并将结构的内存地址交还给您(即, &p为您提供结构的第一个字节地址)。 If it is declared in a function, its life ends when the function exits (ie if function gets out of the scope, you can't reach it).如果它是在函数中声明的,那么它的生命在函数退出时结束(即,如果函数超出范围,则无法访问它)。

  • Alternative 2: Allocates a myStruct width of memory space on heap and a pointer width of memory space of type (struct myStruct*) on stack .选择2:分配myStruct宽度对内存空间和类型的存储器空间中的指针宽度(struct myStruct*)堆叠 The pointer value on the stack gets assigned the value of the memory address of the struct (which is on the heap) and this pointer address (not the actual struct s address) is handed back to you.堆栈上的指针值被分配了结构(在堆上)的内存地址的值,并且这个指针地址(不是实际的struct地址)被交还给你。 It's life time never ends until you use free(q) .在您使用free(q)之前,它的生命周期永远不会结束。

In the latter case, say, myStruct sits on memory address 0xabcd0000 and q sits on memory address 0xdddd0000 ;在后一种情况下,例如, myStruct位于内存地址0xabcd0000q位于内存地址0xdddd0000 then, the pointer value on memory address 0xdddd0000 is assigned as 0xabcd0000 and this is returned back to you.然后,内存地址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)

Addressing the second part of your;解决您的第二部分; when to use which:何时使用哪个:

  • If this struct is in a function and you need to use it after the function exits, you need to malloc it.如果这个struct在函数中,需要在函数退出后使用,就需要malloc You can use the value of the struct by returning the pointer, like: return q;您可以通过返回指针来使用结构体的值,例如: return q; . .
  • If this struct is temporary and you do not need its value after, you do not need to malloc memory.如果这个结构体是临时的,并且之后不需要它的值,则不需要malloc内存。

Usage with an example:用法举例:

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

If we assume both examples occur inside a function, then in:如果我们假设两个例子都出现在一个函数中,那么在:

struct person p = {.name="apple"};

the C implementation automatically allocates memory for p and releases it when execution of the function ends (or, if the statement is inside a block nested in the function, when execution of that block ends). C 实现自动为p分配内存并在函数执行结束时释放它(或者,如果语句在嵌套在函数中的块内,则当该块的执行结束时)。 This is useful when:这在以下情况下很有用:

  • You are working with objects of modest size.您正在处理中等大小的对象。 (For big objects, using many kibibytes of memory, malloc may be better. The thresholds vary depending on circumstances.) (对于大对象,使用许多 kibibytes 的内存, malloc可能更好。阈值因情况而异。)
  • You are working with a small number of objects at one time.您一次处理少量对象。

In:在:

struct person* p_tr = malloc(sizeof(struct person));
p_tr->name = "apple";

the program explicitly requests memory for an object, and the program generally should release that memory with free when it is done with the object.该方案明确要求内存对象,程序一般应释放内存, free当这个对象。 This is useful when:这在以下情况下很有用:

  • The object must be returned to the caller of the function.对象必须返回给函数的调用者。 An automatic object, as used above, will cease to exist (in the C model of computation; the actual memory in your computer does not stop existing—rather it is merely no longer reserved for use for the object) when execution of the function ends, but this allocated object will continue to exist until the program frees it (or ends execution).当函数执行结束时,如上所述的自动对象将不复存在(在 C 计算模型中;计算机中的实际内存不会停止存在——而只是不再保留供对象使用) ,但是这个分配的对象将继续存在,直到程序释放它(或结束执行)。
  • The object is very large.对象非常大。 (Generally, C implementations provide more memory for allocation by malloc than they do for automatic objects.) (通常,C 实现为malloc分配提供的malloc比为自动对象分配的malloc多。)
  • The program will create a variable number of such objects, depending on circumstances, such as creating linked lists, trees, or other structures from input whose size is not known before it is read.该程序将根据情况创建可变数量的此类对象,例如根据输入创建链表、树或其他结构,其大小在读取之前是未知的。

Note that struct person p = {.name="apple"};注意struct person p = {.name="apple"}; initializes the name member with "apple" and initializes all other members to zero."apple"初始化name成员并将所有其他成员初始化为零。 However, the code that uses malloc and assigns to p_tr->name does not initialize the other members.但是,使用malloc并分配给p_tr->name的代码不会初始化其他成员。

If struct person p = {.name="apple"};如果struct person p = {.name="apple"}; appears outside of a function, then it creates an object with static storage duration.出现在函数之外,然后它创建一个具有静态存储持续时间的对象。 It will exist for the duration of program execution.它将在程序执行期间存在。

Instead of struct person* p_tr = malloc(sizeof(struct person));而不是struct person* p_tr = malloc(sizeof(struct person)); , it is preferable to use struct person *p_tr = malloc(sizeof *p_tr); ,最好使用struct person *p_tr = malloc(sizeof *p_tr); . . With the former, a change to the p_tr requires edits in two places, which allows a human opportunity to make mistakes.对于前者,对p_tr的更改需要在两个地方进行编辑,这让人类有机会犯错。 With the latter, changing the type of p_tr in just one place will still result in the correct size being requested.对于后者, p_tr在一个地方更改p_tr的类型仍然会导致请求正确的大小。

struct person p = {.name="apple"};

^This is Automatic allocation for a variable/instance of type person. ^这是为 person 类型的变量/实例自动分配的。

struct person* p_tr = malloc(sizeof(person));

^This is dynamic allocation for a variable/instance of type person. ^这是对 person 类型的变量/实例的动态分配。

Static memory allocation occurs at Compile Time.静态内存分配发生在编译时。 Dynamic memory allocation means it allocates memory at runtime when the program executes that line of instruction动态内存分配意味着它在程序执行该指令行时在运行时分配内存

Judging by your comments, you are interested in when to use one or the other.根据您的评论判断,您对何时使用其中一个感兴趣。 Note that all types of allocation reserve a computer memory sufficient to fit the value of the variable in it.请注意,所有类型的分配都会保留足以容纳其中变量值的计算机内存。 The size depends on the type of the variable.大小取决于变量的类型。 Statically allocated variables are pined to a place in the memory by the compiler.静态分配的变量由编译器固定到内存中的某个位置。 Automatically allocated variables are pinned to a place in stack by the same compiler.自动分配的变量由同一个编译器固定到堆栈中的某个位置。 Dynamically allocated variables do not exist before the program starts and do not have any place in memory till they are allocated by 'malloc' or other functions.动态分配的变量在程序启动之前不存在,并且在由“malloc”或其他函数分配之前在内存中没有任何位置。

All named variables are allocated statically or automatically.所有命名变量都是静态或自动分配的。 Dynamic variables are allocated by the program, but in order to be able to access them, one still needs a named variable, which is a pointer.动态变量由程序分配,但为了能够访问它们,仍然需要一个命名变量,它是一个指针。 A pointer is a variable which is big enough to keep an address of another variable.指针是一个足够大的变量,可以保存另一个变量的地址。 The latter could be allocated dynamically or statically or automatically.后者可以动态或静态或自动分配。

The question is, what to do if your program does not know the number of objects it needs to use during the execution time.问题是,如果您的程序不知道在执行期间需要使用的对象数量,该怎么办。 For example, what if you read some data from a file and create a dynamic struct, like a list or a tree in your program.例如,如果您从文件中读取一些数据并在您的程序中创建一个动态结构,如列表或树,该怎么办。 You do not know exactly how many members of such a struct you would have.您并不确切知道您将拥有这样一个结构体的成员数量。 This is the main use for the dynamically allocated variables.这是动态分配变量的主要用途。 You can create as many of them as needed and put all on the list.您可以根据需要创建任意多个,并将所有内容都放在列表中。 In the simplest case you only need one named variable which points to the beginning of the list to know about all of the objects on the list.在最简单的情况下,您只需要一个指向列表开头的命名变量即可了解列表中的所有对象。

Another interesting use is when you return a complex struct from a function.另一个有趣的用途是当您从函数返回复杂结构时。 If allocated automatically on the stack, it will cease to exist after returning from the function.如果在栈上自动分配,从函数返回后将不复存在。 Dynamically allocated data will be persistent till it is explicitly freed.动态分配的数据将是持久的,直到它被明确释放。 So, using the dynamic allocation would help here.因此,使用动态分配在这里会有所帮助。

There are other uses as well.还有其他用途。

In your simple example there is no much difference between both cases.在您的简单示例中,两种情况没有太大区别。 The second requires additional computer operations, call to the 'malloc' function to allocate the memory for your struct.第二个需要额外的计算机操作,调用'malloc'函数为你的结构分配内存。 Whether in the first case the memory for the struct is allocated in a static program region defined at the program start up time.在第一种情况下,结构的内存是否分配在程序启动时定义的静态程序区域中。 Note that the pointer in the second case also allocated statically.请注意,第二种情况下的指针也是静态分配的。 It just keeps the address of the memory region for the struct.它只保留结构的内存区域的地址。

Also, as a general rule, the dynamically allocated data should be eventually freed by the 'free' function.此外,作为一般规则,动态分配的数据最终应由“free”函数释放。 You cannot free the static data.您无法释放静态数据。

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

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