【问题标题】:Scope struct allocated on the stack在堆栈上分配的范围结构
【发布时间】:2014-08-12 20:54:11
【问题描述】:

我正在阅读和学习 C。我已经阅读了许多类似的问题,但其中大多数似乎是我正在经历的反例,或者我仍然不了解堆上对象分配的概念堆栈。

假设我有一个类似于以下示例的结构:

typedef struct {
    int x;
    char* word;
    struct list_element* next;
}list_element;

我想编写一个函数来初始化list_element 类型的struct。 我将从教科书中学到的东西是使用malloc 在堆上创建结构,这样在初始化函数之外仍然可以看到所有内容。

list_element* init_list_element(int x, char* word) {

    list_element* le = (list_element*)malloc(sizeof(list_element));
    le->word = word;
    le->x = x;

    return le;
}

为了真正理解这个主题,我尝试编写一个替代初始化函数,在堆栈上分配struct。稍后尝试访问属性时应该会导致错误,因为变量应该已经超出范围。

list_element init_list_element(int x, char* word) {
    list_element le;
    le.word = word;
    le.x = x;

    return le;
}

但是,当使用第二个实现创建结构并尝试访问例如属性 x 时,代码不会中断。为什么是这样?变量le 不应该超出范围并因此在尝试打印其属性时无法访问吗?

list_element test = init_list_element(123,"test");
printf("%s, %i", test.word, test.x);

【问题讨论】:

    标签: c struct scope


    【解决方案1】:
    list_element test = init_list_element(123,"test");
    

    您正在创建在第二个函数中创建的结构的副本,因此您仍然可以访问它,但它只是一个副本。

    在 C 中,您分配给变量的所有内容都是一个副本。

    例子:

    list_element le1 = {1, NULL, NULL};
    list_element le2 = le1;
    

    le2 将包含 le1 的副本,而不是原始 le1。换句话说,以下内容不会改变 le1 的值:

    le2.x = 3;
    printf("%d",le1.x); // 1
    printf("%d",le2.x); // 3
    

    【讨论】:

    • 所以如果我原来的问题中的第二个函数也返回一个指针,并且我返回 &le 和在堆栈上创建的 list_element ,那么会有错误吗?
    • 如果您尝试返回局部变量的地址,它应该会给出警告。所以最好的方法是使用 malloc 在堆中保留一些空间@tim_a
    【解决方案2】:

    变量le 已超出范围,但您没有访问leinit_list_element() 函数返回le 的副本,并将该副本的内容分配给test

    然后test 的成员包含与le 最初相同的数据。

    【讨论】:

      猜你喜欢
      • 2013-10-20
      • 2011-01-25
      • 2019-10-25
      • 2010-09-17
      • 1970-01-01
      • 2014-10-16
      • 2021-07-09
      • 2021-04-01
      相关资源
      最近更新 更多