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

Why can we initialize inside a function and still use that value outside the function?

例如:

#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以及栈和堆的区别。当我们在函数alloc_and_init_some_thing中声明并初始化变量si时,这个值不是已经存在于栈中了吗?因此它应该在函数完成时被清除?

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

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

这是为什么?

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

同样的事情发生在类似的功能中。

你是对的,"si" 和 "j" 的生命周期仅限于它们各自的功能,并且在这些功能的 return 之后不可用。但是,它们的内容已在函数 return 之前通过 malloc/memcpy 复制,并且指向副本的指针存储在变量 "s" 和 "i" 中,它们仍然存在在打印(或使用)这些副本时。