C 如何为函数中的结构正确分配内存以返回其值供以后使用,以及如何将结构强制转换为指针?

C 如何为函数中的结构正确分配内存以返回其值供以后使用,以及如何将结构强制转换为指针?,c,pointers,memory,struct,C,Pointers,Memory,Struct,我目前正在自学C,以便掌握一个大学项目。在该项目中,我们有几个签名,这些签名是为了解决我们的任务而需要实现的。经过几个小时的努力取得了一些进展,我必须承认我对函数的返回类型完全感到困惑。我将向您展示一些代码: 这是一种表示以32为基数的幂的数字的结构 #include <stdio.h> #include <stdlib.h> typedef unsigned int uint32; typedef struct { int n; uint32* words;

我目前正在自学C,以便掌握一个大学项目。在该项目中,我们有几个签名,这些签名是为了解决我们的任务而需要实现的。经过几个小时的努力取得了一些进展,我必须承认我对函数的返回类型完全感到困惑。我将向您展示一些代码:

这是一种表示以32为基数的幂的数字的结构

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

typedef unsigned int uint32;
typedef struct 
{
  int n;
  uint32* words;
}
foo;
如您所见,该函数将指向结构的两个指针作为参数,并返回结构的值,而不是指向结构的指针。这意味着我必须在本地创建一个foo实例并返回它

foo add(foo* a, foo* b)
{
  foo result = {1, malloc(sizeof(uint32))};
  // do something with result
  return result;
}
1)这次尝试有什么错误吗?在我的生产代码中,我在访问返回的结构的值时遇到了问题:在返回结构后,它们似乎发生了变化。不幸的是,我无法在一个更简单的应用程序中重现这种行为,这让我更加担心我做的都是错的。我还尝试使用malloc为变量result分配内存,但这似乎只有在创建指向foo的指针时才起作用,因为我无法返回指针,这似乎是没有选项的

2) 我正在寻找一种将返回类型(可能不是正确的术语)转换回指针的方法。 让我们假设我有以下代码:

   foo* bar1 = malloc(sizeof(foo));
   bar1->n = 1;
   bar1->words = malloc(bar1->n * sizeof(uint32));
   bar1->words[0] = 4294967295;
   foo* bar2 = malloc(sizeof(foo));
   bar2->n = 1;
   bar2->words = malloc(bar2->n * sizeof(uint32));
   bar2->words[0] = 21;
   foo bar3 = add(bar1, bar2);
很好。我现在如何使用bar3的值再次调用add函数。像这样:

   foo bar4 = add(bar1, bar3);

After还尝试了创建foo*和分配值的各种尝试,但都失败了,我决定发布这个问题,以获得一些好的答案,帮助我更好地理解C。

您正在查找运算符的地址,&&foo3将返回一个指向foo3的指针。

更新我收回先前的解释。我通过valgrind运行了您的代码,事实上,您不会产生任何泄漏或错误的内存访问。按照您的方式,结构是按值返回的,因此在返回时会将其复制到新结构中。完成后,您唯一需要做的就是
free()
单词指针

你奇怪的结果可能是你正在做的事情的结果,这里没有显示

您需要返回指向foo的指针:

foo* add (foo* a, foo* n) {
  foo result* = malloc(...);

  /* do some addition */

  return result;
}
不要忘记
free()
通过这种方式获得的
foo
结构

到unDrTrand您的方法不起作用的原因,考虑在<代码> Advices()/代码>作用域中声明的变量的生存期:

  • 已输入
    add()
  • 将创建一个新的
    foo
    结构,并将其分配给变量
    result
  • 函数
    add()
    返回并释放该范围内变量的内存
  • add()
    之外,调用方接收存储在内存中标记为未使用的位置的结构
  • 尝试访问该结构会产生未定义的结果,因为它所在的内存可能会分配给其他数据
  • 考虑我提出的解决方案流程:

  • 已输入
    add()
  • 在堆上分配新内存,该内存的地址存储在
    result
  • 函数
    add()
    返回
    result
    的值(表示内存中地址的整数)
  • add()
    之外,
    result
    指向的位置仍然是堆上的分配位置,返回的指针可以安全地取消引用
  • 在该位置使用完结构后,调用
    free(result)
    ,该位置被标记为未使用
  • 希望有帮助!有关更多信息,您应该研究内存堆是什么以及分配是如何工作的。

    1)要访问返回的结构,您只需要执行以下操作:

     printf("[bar3] n %d words %d\n", bar3.n, *(bar3.words));
    
    2) 要将
    bar3
    再次传递到函数
    add
    。您需要传递bar3的mem地址,该地址可通过操作员
    访问:

       foo bar4 = add(bar1, &bar3);
    


    如果这样做,则可以保留函数的定义而不返回指针。

    Edited:我不能使用返回foo*的函数签名。我要还福。我还尝试了foo result=malloc(sizeof(foo));但这只会给我一个编译错误,说明我使用了无效的初始值设定项。我更新了我的答案,你需要执行
    foo*result=malloc(…)
    ,我输入了一个错误。您的函数必须返回一个
    foo*
    ,才能按照您描述的方式工作。谢谢您的回答。好的,你证明了我对堆栈/堆上内存管理的变量作用域的理解是正确的。让我困惑的是,这个函数的签名必须与我在问题中发布的签名匹配。(由大学给出)我必须归还foo,我不能归还foo*。根据你的帖子和我对内存分配的理解,我似乎不知道该怎么做。为什么你必须返回
    foo
    ?为什么签名是固定的?也许如果你发布真实的代码,问题就显而易见了。另一种可能性是,您可以修改传入的
    foo
    之一,而不是返回
    foo
    。因为该方法的签名在大学提供的需求规范中给出。(我知道这个任务与现实世界中的任何应用程序都相去甚远,但不幸的是,我必须以这种方式编写代码才能通过笔试。)@citronas:我要说得清楚一点——在示例
    add()
    函数中,返回
    struct
    的方式没有任何问题。在您的完整程序中,问题很可能是您分配s的
    单词
    成员的方式
    
       foo bar4 = add(bar1, &bar3);
    
    foo bar3_p = &bar3;
    foo bar4 = add(bar1, bar3_p);