2

我必须从另一个函数中分配一个结构,显然是使用指针。我已经盯着这个问题看了好几个小时,并尝试了上百万种不同的方法来解决它。

这是一些示例代码(非常简化):

...
some_struct s;
printf("Before: %d\n", &s);
allocate(&s);
printf("After: %d\n", &s);
...

/* The allocation function */
int allocate(some_struct *arg) {

arg = malloc(sizeof(some_struct));
printf("In function: %d\n", &arg);

return 0;
}

这确实在分配调用之前和之后给了我相同的地址:

Before: -1079752900
In function: -1079752928
After: -1079752900

我知道这可能是因为它在函数中创建了一个副本,但我不知道如何实际处理我作为参数给出的指针。我尝试定义 some_struct *s 而不是 some_struct s,但没有运气。我试过:

int allocate(some_struct **arg)

这工作得很好(分配函数也需要更改),但根据分配我可能不会更改声明,它必须是 *arg .. 如果我只需要声明,那将是最正确的some_struct s.. 不是 some_struct *s。分配函数的目的是初始化一个结构体(a some_struct),其中也包括分配它。

还有一件事我忘了提。分配函数中的返回 0 是为某些状态消息保留的,因此我无法使用它返回地址。

4

6 回答 6

4

通常,我会从以下位置返回指针allocate

void * allocate()
{
    void * retval = malloc(sizeof(some_struct));
    /* initialize *retval */
    return retval;
}

如果你想在参数中返回它,你必须传递一个指向参数的指针。由于这是指向 some_struct 的指针,因此您必须将指针传递给指针:

void allocate (some_struct ** ret)
{
    *ret = malloc(sizeof(some_struct));
    /* initialization of **ret */
    return;
}

被称为

some_struct *s;
allocate(&s);
于 2010-04-08T15:56:37.187 回答
1
int func(some_struct *arg) {
    arg = malloc(sizeof(some_struct));
    ... 
}

在这里,您只需将 malloc 的结果分配给局部arg变量。指针在 C 中按值传递,指针的副本被传递给函数。您不能以这种方式更改调用者的指针。请记住指针的区别及其指向的内容。

您有多种选择:

从函数返回指针:

 some_struct *func(void) {
    arg = malloc(sizeof(some_struct));
    ...
    return arg;
}
...
some_struct *a = func();

在调用者中分配结构:

 int func(some_struct *arg) {
    ...
    arg->something = foo;

}
... 
some_struct a;
func(&a);

或者动态分配

some_struct *a = malloc(sizeof *a);
func(a);

使用指向调用者指针的指针:

 int func(some_struct **arg) {
    *arg = malloc(sizeof **arg);

}
... 
some_struct *a;
func(&a);

使用全局变量(丑陋..)

 some_struct *global;
 int func(void) {
    global = malloc(sizeof *global);

}
 ... 
some_struct *a;
func();
a = global;
于 2010-04-08T16:00:37.237 回答
1

我非常怀疑这是您老师的想法,但是您可以使用一系列合法的类型转换来作弊。

   int allocate(some_struct *arg) 
   /* we're actually going to pass in a some_struct ** instead. 
      Our caller knows this, and allocate knows this.  */
   { 
      void *intermediate = arg;  /* strip away type information */
      some_struct **real_deal = intermediate;  /* the real type */
      *real_deal = malloc(sizeof *real_deal); /* store malloc's return in the 
                                                 object pointed to by real_deal */
      return *real_deal != 0;  /* return something more useful than always 0 */
   }

然后你的调用者做同样的事情:

   {
      some_struct *s; 
      void *address_of_s = &s; 
      int success = allocate(address_of_s); 
      /* what malloc returned should now be what s points to */
      /* check whether success is non-zero before trying to use it */
   }

这依赖于 C 中的一条规则,即任何指向对象的指针都可以隐式转换为 void 指针,反之亦然,而不会丢失。

请注意,正式这是未定义的,但它几乎肯定会起作用。虽然任何对象指针值都需要能够void*无损地转换为 a 并返回,但语言中没有任何东西可以保证 a可以无损some_struct*地存储 a 。some_struct**但它很有可能工作得很好。

你的老师让你别无选择,只能编写正式的非法代码。除了这样的“作弊”之外,我看不到您还有其他选择。

于 2010-04-08T16:13:25.273 回答
0

你不能这样做。您不能按值声明结构,然后按地址更改它。

于 2010-04-08T15:53:32.097 回答
0
some_struct *s;
printf("Before: %d\n", s");
allocate(&s);
printf("After: %d\n", s");
...

/* The allocation function */
int allocate(some_struct **arg) {

*arg = malloc(sizeof(some_struct));
printf("In function: %d\n", *arg");

return 0;
}

您需要修改结构的指向值。所以你需要另一个级别的间接,因此你必须发送一个指向结构指针的指针。

于 2010-04-08T15:53:52.470 回答
0

嗯,C 使用按值传递,这意味着函数获取其参数的副本,并且对这些副本所做的任何更改都不会影响调用者中的原始参数。

/* The allocation function */
int allocate(some_struct *arg) {

arg = malloc(sizeof(some_struct));
printf("In function: %d\n", &arg");

return 0;
}

在这里,您传入 some_struct 的地址。然后你丢弃该地址,并用 malloc 返回的任何内容替换它。然后你返回,malloc 的返回值永远丢失了,你已经泄漏了内存。而且你的 some_struct 没有改变。它仍然具有初始化为的任何随机数,您将其打印出来。

如果您可能不更改 allocate 函数的签名,它永远不会有用。它必须要么获取一个指针的地址,以便它可以修改该指针的值,要么它必须返回一个您的调用者可以隐藏的指针。

于 2010-04-08T15:59:52.433 回答