使用指定初始化器与堆的相关内容

4

可以像下面展示的那样使用指定初始化器(对于“billy”)而不会出现问题,但是当相同的初始化方法用于动态内存时,将在编译时出现错误。

使用指定初始化器有哪些限制?

除了我们要写入的位置(即地址)之外,是什么使这两种初始化不同?为什么我们不能在动态内存中使用指定初始化器?

struct student{
    char *name; 
    int age;
};


void print_student(struct student* st){
    printf("Student: %s is %d years old\n", st->name, st->age);
}


int main(void) {    
    srand(time(NULL));
    struct student *molly_ptr = malloc(sizeof(struct student));

    struct student billy = {
                            .name = "billy",
                            .age = rand()%30
                           };

    *molly_ptr = {
                    .name = "molly",
                    .age = 25
                 };

    //molly_ptr->name = "molly";
    //molly_ptr->age = 25;

    print_student(&billy);
    print_student(molly_ptr);


    return 0;
}

error: expected expression before '{' token
  *molly_ptr = {
               ^

2
初始化和赋值是两个不同的概念。你正在尝试做的第二件事是赋值。据我所知,那种语法在此情况下是不可用的。(与堆栈无关。) - Mat
最好将char *name声明为const char *name - Lundin
@Lundin,这段代码只是针对这个问题而生成的。从技术上讲,还存在内存泄漏问题。 - sherrellbc
@Lundin:严格来说不算,但现实情况并非如此。在 main 结束之前,每个资源都已被释放,而且您的操作系统配备了内存管理系统,会在进程结束后自动释放所有内存。例如 Git 并不会释放任何资源。 - Leandros
2个回答

8

使用复合字面量:

*molly_ptr = ( struct student ){ .name = "molly", .age = 25 };

这几乎与以下内容完全相同:

struct student temp = { .name = "molly", .age = 25 };
*molly_ptr = temp;

非常有趣,尽管此源代码(https://gcc.gnu.org/onlinedocs/gcc/Compound-Literals.html)建议指向的数据现在位于堆栈上。这将导致上面的代码泄漏内存。我不知道这种语法。 - sherrellbc
1
@sherrellbc 错误。molly_ptr仍然指向分配的内存。整个结构体被复制到那块内存中。这一点在我的第二个示例中非常清楚地表明了。 - 2501
这是一件非常有趣的事情,我不知道你们谁是对的。如果这是C++代码,我可以看到它被复制了,但由于这是C,我认为指针只是指向堆栈上的某个东西。有什么可以澄清这个问题的吗?这可能会成为一个很好的问题。 - callyalater
@callyalater,我们对指向struct student对象的指针进行解引用,然后赋值将结构体深度复制到内存中。根据文档的描述,复合字面量创建一个未命名的对象(根据其内容和修饰符自动或静态持续时间),编译器生成深度复制指令。请阅读C++文档的最后两段以获取注意事项。 - sherrellbc
1
@sherrellbc:看到你链接的汇编代码,有趣的是复合字面量赋值和单独赋值创建了相同的汇编代码。 - Leandros
显示剩余7条评论

4

你需要写:

*molly_ptr = (struct student){
                                .name = "molly",
                                .age = 25
                             };

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接