为什么我们可以在函数内部进行初始化,而仍然在函数外部使用该值?

时间:2019-07-13 17:14:52

标签: c pointers initialization stack heap-memory

例如:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

typedef struct {
    int n;
    double d;
} some_thing;

void alloc_and_init_some_thing(some_thing** s, int n, double d) {
    some_thing si = { .n=n, .d=d };
    *s = malloc(sizeof(**s));
    memcpy(*s, &si, sizeof(**s));
}

void alloc_and_init_int(int **i) {
    int j = 21; 
    *i = malloc(sizeof(**i));
    memcpy(*i, &j, sizeof(**i));
}

int main() {
    some_thing *s;
    alloc_and_init_some_thing(&s, 41, 31);
    printf("s->n=%d s->d=%f\n", s->n, s->d);

    int *i; 
    alloc_and_init_int(&i);
    printf("*i=%d\n", *i);
    return 0;
}

我仍在学习C以及堆栈和堆之间的区别。当我们在函数si中声明并初始化变量alloc_and_init_some_thing时,堆栈中是否不存在该值?因此,当函数完成时应该清除掉它吗?

但是我可以看到实际上并没有发生。回到主函数中,当我们打印s->n时,我们得到的值是41

类似地,当我们在主函数中打印*i的值时,它也会打印21

那是为什么?

2 个答案:

答案 0 :(得分:3)

memcpy(*s, &si, sizeof(**s));行将堆栈上的结构si复制到堆分配的结构s中,因此由于可以在程序中的任何位置访问堆分配,因此使其持久化在内存中。它只是指向内存中地址的指针。

类似的功能也会发生同样的事情。

答案 1 :(得分:1)

您是正确的,“ si”和“ j”的生存期仅限于它们各自的功能,并且在从这些功能返回后不可用。但是,它们的内容已在返回函数之前通过malloc / memcpy复制,并且指向副本的指针存储在变量“ s”和“ i”中,在打印(或使用)变量时它们仍然有效副本。