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

Ama*_*nda 7 c malloc struct

有人可以向我解释一下创建带有和不带有 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)

两者之间到底有什么区别?什么时候会使用一种方法而不是其他方法?

ssd*_*ssd 6

具有如下数据结构;

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位于内存地址0xabcd0000q位于内存地址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)


Eri*_*hil 5

如果我们假设这两个示例都发生在函数内部,则:

\n\n
struct person p = {.name="apple"};\n
Run Code Online (Sandbox Code Playgroud)\n\n

C 实现会p在函数执行结束时自动分配内存并释放内存(或者,如果语句位于函数中嵌套的块内,则在该块执行结束时释放内存)。这在以下情况下很有用:

\n\n
    \n
  • 您正在处理尺寸适中的物体。(对于大对象,使用许多 KB 的内存malloc可能会更好。阈值根据情况而变化。)
  • \n
  • 您一次正在处理少量对象。
  • \n
\n\n

在:

\n\n
struct person* p_tr = malloc(sizeof(struct person));\np_tr->name = "apple";\n
Run Code Online (Sandbox Code Playgroud)\n\n

程序显式地为对象请求内存,并且程序通常应该在free处理完该对象后释放该内存。这在以下情况下很有用:

\n\n
    \n
  • 该对象必须返回给函数的调用者。上面使用的自动对象在执行时将不再存在(在计算的 C 模型中;计算机中的实际内存不会停止存在\xe2\x80\x94,而只是不再保留供该对象使用)函数结束,但是这个分配的对象将继续存在,直到程序释放它(或结束执行)。
  • \n
  • 该物体非常大。(通常,C 实现比malloc自动对象提供更多的内存用于分配。)
  • \n
  • 程序将根据具体情况创建可变数量的此类对象,例如从读取之前不知道其大小的输入创建链表、树或其他结构。
  • \n
\n\n

请注意,将成员struct person p = {.name="apple"};初始化name"apple"并将所有其他成员初始化为零。malloc但是,使用和分配的代码p_tr->name不会初始化其他成员。

\n\n

如果struct person p = {.name="apple"};出现在函数外部,则它将创建一个具有静态存储持续时间的对象。它将在程序执行期间存在。

\n\n

相反struct person* p_tr = malloc(sizeof(struct person));,最好使用struct person *p_tr = malloc(sizeof *p_tr);. 对于前者,更改p_tr需要在两个地方进行编辑,这使得人类有机会犯错误。对于后者,仅更改一处的类型p_tr仍将导致请求正确的大小。

\n