我必须从另一个函数中分配一个结构,显然是使用指针。 我一直盯着这个问题好几个小时,并尝试了一百万种不同的方法来解决它。
这是一些示例代码(非常简化):
...
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;
}
这确实给了我在allocate-call之前和之后的相同地址:
Before: -1079752900
In function: -1079752928
After: -1079752900
我知道这可能是因为它在函数中复制,但我不知道如何实际处理我给出的指针作为参数。我尝试定义some_struct * s而不是some_struct,但没有运气。我尝试过:
int allocate(some_struct **arg)
工作正常(分配函数也需要更改),但根据作业我可能不会更改声明,而且它必须是* arg ..如果我只是它是最正确的必须声明some_struct s ..不是some_struct * s。 分配函数的目的是初始化一个struct(some_struct),它还包括分配它。
我还忘了提一件事。分配函数中的返回0保留用于某些状态消息,因此我无法使用此返回地址。
答案 0 :(得分: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);
答案 1 :(得分: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;
答案 2 :(得分: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*
而不会丢失,但语言中没有任何内容可以保证some_struct*
可以保存some_struct**
而不会丢失。但是很有可能工作得很好。
你的老师别无选择,只能写正式的非法代码。除了像这样“作弊”之外,我没有看到你有任何其他选择。
答案 3 :(得分:0)
你不能这样做。您不能按值声明结构,然后按地址更改它。
答案 4 :(得分: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;
}
您需要修改结构的指向值。因此,您需要另一级别的间接,因此您必须发送指向结构指针的指针。
答案 5 :(得分:0)
嗯,C使用pass-by-value,这意味着函数会获取其参数的副本,对这些副本所做的任何更改都不会影响调用者中的原始文件。
/* 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没有改变。它仍然有你初始化的随机数,你打印出来的。
如果您不能更改分配功能的签名,则它永远不会有用。它必须获取指针的地址,以便它可以修改该指针的值,或者它必须返回一个指针,调用者可以丢弃它。