另一个函数内的 Malloc

发布于 2024-08-28 03:31:01 字数 873 浏览 6 评论 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;
}

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

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),其中还包括分配它。

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

I have to allocate a struct from within another function, obviously using pointers.
I've been staring at this problem for hours and tried in a million different ways to solve it.

This is some sample code (very simplified):

...
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;
}

This does give me the same address before and after the allocate-call:

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

I know it's probably because it makes a copy in the function, but I don't know how to actually work on the pointer I gave as argument. I tried defining some_struct *s instead of some_struct s, but no luck. I tried with:

int allocate(some_struct **arg)

which works just fine (the allocate-function needs to be changed as well), BUT according to the assignment I may NOT change the declaration, and it HAS to be *arg.. And it would be most correct if I just have to declare some_struct s.. Not some_struct *s.
The purpose of the allocation function is to initialize a struct (a some_struct), which also includes allocating it.

One more thing I forgot to mention. The return 0 in the allocate function is reserved for some status messages and therefore I can't return the address using this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

酷炫老祖宗 2024-09-04 03:31:01

通常,我会从 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);

Typically, I'd return the pointer from allocate:

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

If you want to return it in a parameter, you have to pass a pointer to the parameter. Since this is a pointer to a some_struct, you have to pass a pointer to a pointer:

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

to be called as

some_struct *s;
allocate(&s);
相权↑美人 2024-09-04 03:31:01

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

   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* 并返回,但该语言中没有任何内容可以保证 some_struct* 可以存储some_struct** 无损失。但它很有可能工作得很好。

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

I highly doubt this is what your teacher had in mind, but you can cheat using a series of legal type conversions.

   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 */
   }

Then your caller does the same:

   {
      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 */
   }

This relies on a rule in C that says any pointer to an object can be implicitly converted to a void pointer, and vice-versa, without loss.

Note that formally this is undefined, but it is all but sure to work. While any object pointer value is required to be able to convert to a void* and back without loss, there is nothing in the language that guarantees that a some_struct* can store a some_struct** without loss. But it has a very high likelihood of working just fine.

Your teacher gave you no option but to write formally illegal code. I don't see that you have any other option besides "cheating" like this.

少钕鈤記 2024-09-04 03:31:01
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;
int func(some_struct *arg) {
    arg = malloc(sizeof(some_struct));
    ... 
}

Here you just assign the result of malloc to the local arg variable. pointers are passed by value in C, a copy of the pointer gets passed to the function. You cannot change the pointer of the caller this way. Keep in mind the difference in a pointer and what it points to.

You have various options:

Return the pointer from the function:

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

Allocate the structure in the caller:

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

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

Or dynamically allocate it

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

Using a pointer to the callers pointer:

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

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

Use a global variable (ugly..)

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

}
 ... 
some_struct *a;
func();
a = global;
各自安好 2024-09-04 03:31:01

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

You can't do it this way. You can't declare a struct by value, and then change it by address.

挽清梦 2024-09-04 03:31:01
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;
}

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

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;
}

You need to modify the pointed value for the struct. So you need another level of indirection, thus you have to send a pointer to the struct pointer.

迎风吟唱 2024-09-04 03:31:01

嗯,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 尚未更改。它仍然具有您打印出来的初始化时的随机数。

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

Well, C uses pass-by-value, which means that functions get copies of their arguments, and any changes made to those copies don`t affect the original in the caller.

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

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

return 0;
}

Here you pass in the address of your some_struct s. Then you discard that address, and replace it with whatever was returned by malloc. Then you return, and the return value of malloc is lost forever, and you've leaked memory. And your some_struct s has not been changed. It still has whatever random number it was initialized to, which you printed out.

If you may not change the signature of the allocate function, it can never be useful. It must either take the address of a pointer, so that it can modify the value of that pointer, or it must return a pointer that your caller can tuck away.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文