使用malloc和不使用malloc创建结构的差异

14 浏览
0 Comments

使用malloc和不使用malloc创建结构的差异

有人可以向我解释一下使用malloc和不使用malloc创建结构之间的区别吗?什么时候应该使用malloc,什么时候应该使用常规初始化?\n例如:\n

结构体 person {
    char* name;
};
结构体 person p = {.name="apple"};
结构体 person* p_tr = malloc(sizeof(struct person));
p_tr->name = "apple";

\n这两种方式的区别是什么?在什么情况下会选择其中一种方法?

0
0 Comments

在创建结构时使用malloc和不使用malloc之间的区别是什么?这个问题的出现的原因是因为在程序中,创建结构时有两种不同的内存分配方式:静态分配和动态分配。静态内存分配发生在编译时,而动态内存分配则在程序执行时分配内存。

静态分配是在编译时分配内存空间,可以通过直接声明变量来创建结构。例如:struct person p = {.name="apple"}; 这种方式是自动分配内存。

动态分配是在运行时分配内存空间,需要使用malloc函数来动态分配内存。例如:struct person* p_tr = malloc(sizeof(person)); 这种方式是动态分配内存。

那么如何使用这两种不同的内存分配方式呢?它们有什么区别呢?

静态分配可以在程序的生命周期内预先分配内存,因为在编译时就已经确定了所需的内存空间。这样做有多种好处,比如节省了在运行时分配内存所需的时间。

动态分配则可以在程序的生命周期内给程序员更多的内存管理控制权。在运行时分配一块内存后,可以根据需要选择释放或保留内存。这样做给了程序员更多的控制权,但也需要承担更多的责任。

静态分配适用于在程序运行期间已知所需内存大小、变量数量或实例数量的情况,而动态分配适用于需要在运行时根据需求进行内存管理的情况。

更多关于这两种内存分配方式的解释可以在以下链接中找到:stackoverflow.com/a/8385488/11973277

0
0 Comments

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

在上述例子中,当我们假设这两个示例都在一个函数中时,对于以下代码:

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

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

- 当你正在处理的对象大小适中时(对于大对象,使用许多kibibytes的内存,malloc可能更好。具体的阈值取决于具体情况)。

- 当你一次只处理少量对象时。

而在以下代码中:

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

程序显式地请求内存来存储对象,并且通常应该在使用完对象之后使用free释放内存。这在以下情况下非常有用:

- 对象必须返回给函数的调用者。自动对象(如上述代码中使用的)在函数执行结束时将不再存在(在C模型中是这样,实际内存并不会消失,而是不再保留给该对象使用),但是这个分配的对象将继续存在,直到程序释放它(或者程序执行结束)。

- 对象非常大。(通常,C实现提供给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的类型,仍然会请求正确的大小。

0
0 Comments

在上述内容中,出现了两种创建结构体的方式:使用malloc和不使用malloc。问题的原因是为了解释这两种方式的区别。解决方法是提供了使用示例和建议。下面是对这些内容的整理:

在C语言中,创建结构体有两种方式:

1. 不使用malloc:在栈上分配一块myStruct大小的内存空间,并返回结构体的内存地址。如果在函数中声明结构体,则其生命周期在函数退出时结束,即在超出作用域后无法访问。

2. 使用malloc:在堆上分配一块myStruct大小的内存空间,并在栈上分配一个指向(struct myStruct*)类型的内存空间。栈上的指针值被赋予指向结构体在堆上的内存地址的值,并将该指针地址(而不是实际结构体的地址)返回给调用者。只有在使用free(q)之后,内存才会被释放。

使用示例:

1. 如果结构体在函数中使用,并且在函数退出后仍需要访问它,需要使用malloc进行内存分配。可以通过返回指针的方式使用结构体的值,例如:return q;

2. 如果结构体是临时的,并且在使用后不再需要其值,则无需使用malloc进行内存分配。

下面是一个使用示例:

struct myStruct {
    int a;
    char *b;
};
struct myStruct *foo() {
    struct myStruct p;
    p.a = 5;
    return &p; // 注意,此时p已超出作用域,可能会有警告
}
struct myStruct *bar() {
    struct myStruct *q = malloc(sizeof(struct myStruct));
    q->a = 5;
    return q;
}
int main() {
    struct myStruct *pMain = foo();
    // 在foo中分配了内存,p.a被赋值为'5'
    // 返回了一个内存地址
    // 但要小心!!!
    // 内存易被覆写
    // 这是无法控制的
    struct myStruct *qMain = bar();
    // 在bar中分配了内存,q->a被赋值为'5'
    // 返回了一个内存地址
    // 内存不易被覆写
    // 直到使用'free(qMain);'释放为止
}

文章中还提到了使用C标准术语回答C语言问题的偏好,同时指出malloc提供的内存是"allocated"而不是"heap"。同时还指出,虽然硬件栈通常用于实现自动存储,但C标准并不要求使用硬件栈,并且某些特殊用途的C实现(例如资源受限的特殊系统)可能不使用硬件栈。

0