【问题标题】:How can I return different address of structs?如何返回不同的结构地址?
【发布时间】:2021-12-24 18:15:16
【问题描述】:

我在主函数中有一个结构数组,我想保存几个结构的数据。我正在使用一个接收所需数据并将其放入函数中定义的结构的函数。 在过程结束时,我返回这个结构的地址。 但是如果我多次调用这个函数,它总是定义相同的结构地址,所以我会丢失上一次调用的数据。

#include<stdio.h>

struct data {
    int day;
};

struct data* Dates(int val);

int main() {
    struct data* Dates1[3];
    int array[] = { 12, 15, 2021 };

    for (int i = 0; i < 3; i++) {
        Dates1[i] = Dates(array[i]);   
    }
}

struct data* Dates(int val)  {
    struct data Date;
    Date.day = val;
    return &Date; ///AFTER EVERY CALL TO THIS FUNCTION IT RETURN THE SAME ADDRESS!!!
}

【问题讨论】:

  • 您不能从函数中返回局部变量。打开你的警告——你的编译器应该向你抱怨这个。相反,要么返回一个struct data(并将其直接存储在您的数组中),要么返回一个malloc()(并由调用者free()ed)。
  • 如果您使用正确的警告选项进行编译,您的编译器会抱怨您甚至尝试这样做。其实GCC默认开启-Wreturn-local-addr,Clang默认开启-Wreturn-stack-address。您是否可能因为它“只是”一个警告而忽略它?您可以添加-Werror,以便您不能忽略警告。

标签: c


【解决方案1】:

当您调用一个函数时,它会创建一个堆栈帧。该函数的局部变量在该堆栈帧内分配。当函数退出时,堆栈帧被“销毁”。该内存可以重复使用。

您会看到这种行为,因为每次在循环中调用该函数时,它都会重用相同的内存空间。

您不能依赖当前函数调用之外的堆栈上分配的变量地址的有效性。如果您需要在函数调用后继续存在值,则需要动态分配它 - 通常使用 malloc。完成后不要忘记free那段记忆。

【讨论】:

  • 使用 malloc 请求内存后,我不知道如何写入结构中的正确字段。例如,如果我想写入日期字段,我有一个错误。 struct data* Date = malloc(sizeof(struct data); Date.day = val; return &Date;
  • 在这种情况下,Date 是一个指针。为了访问字段,您必须取消引用指针。 (*Date).day = val; 有一个方便的语法:Date-&gt;day = val;。而Date 已经是一个指针,所以你在返回它时不需要检索 _its 的地址,否则你会有一个struct data **
【解决方案2】:

你必须把你的函数写成这样:

struct data* Date = (struct data*) malloc(sizeof(struct data))
Date->day = val;
return Date;

之后,当指针不再使用时,您必须在指针上调用 free()。 (如果不是这称为内存泄漏)

当您感到困惑时,请记住一个简单的规则,即您只能将指针返回到创建变量指向的调用级别。 如果您想了解为什么会这样,您应该阅读什么是调用堆栈以及堆栈变量的工作原理。

【讨论】:

    【解决方案3】:

    如果您不想使用malloc,另一种方法是让函数接收指向未初始化值void Dates(struct data *, int); 的指针,然后调用者负责内存。

    #include <stdio.h>
    #include <assert.h>
    
    struct data {
        int day;
    };
    
    static void Dates(struct data *const data, const int val) {
        assert(data); /* Defensive debug. */
        data->day = val;
    }
    
    int main(void) {
        int array[] = { 12, 15, 2021 };
        struct data dates1[sizeof array / sizeof *array];
    
        for(int i = 0; i < sizeof dates1 / sizeof *dates1; i++)
        {
            Dates(dates1 + i, array[i]);
            printf("%d: %d\n", i, dates1[i].day);
        }
    }
    

    当人们想要一个与内存分配无关的功能时,这可能更适合;在这个例子中,我在堆上而不是动态地保留内存。

    【讨论】:

      猜你喜欢
      • 2020-11-07
      • 1970-01-01
      • 1970-01-01
      • 2017-11-29
      • 1970-01-01
      • 2016-02-24
      • 1970-01-01
      • 1970-01-01
      • 2019-11-01
      相关资源
      最近更新 更多