1

我对如何通过引用在函数中传递指针感到有些困惑?

例如,这是我编写的一些代码(我没有复制整个函数,只是其中相关的部分)

  metadata * removeBlock(metadata *first)
{

    metadata *temp = first;
    if(first == NULL || first -> prev == NULL)
        {
            first -> in_use = 1;
            first = NULL;
            return temp;
        }
}

我想要的是,当函数返回时,传入的原始值应该设置为NULL。这是我调用函数的方式,(这行代码将从堆中的一个区域中提取一个元数据结构,它工作正常,我已经调试并确保在此之后,struct 确实指向一个有效的元数据结构)

metadata *strct = ((metadata *)ptr - sizeof(metadata));
removeBlock(strct);

但是,在此方法返回后,strct 仍然是我在函数中传递它之前的值。我尝试传入 &strct,但这只是抛出了一个无效的强制转换异常。将结构作为参数传递的最佳方法是什么?

谢谢你。

4

5 回答 5

2

我认为您想要的不是一个好的设计 - 如果您的函数的用户希望将指针设置为 null(为什么?)使用函数的返回值重置值是有意义的。

无论如何,您需要一个指向指针的指针,如下所示:

metadata* removeBlock(metadata** first) {

    metadata* temp = *first;
    if( temp == NULL ) return temp;

    if( temp->prev == NULL ) {
        temp->in_use = true;
        *first = NULL;
    }
    return temp;
}

metadata* strct = ((metadata*)ptr - sizeof(metadata));
removeBlock(&strct);
于 2013-04-26T01:27:15.953 回答
1

正如@SheerFish 所说,我们在 C 中所拥有的只是按值传递。但是,可以使用指针模拟传递引用。

void func(struct foo **fooptr) { *fooptr = 0; }
int main(int argc, char **argv) { struct foo *fooptr; func(&fooptr); }

这是传递一个指向ptr变量值的指针(不管该值是否是指针),允许函数使用*ptr. 这种技术有时被称为按地址传递,并且是最接近 C 必须按引用传递的技术。

于 2013-04-26T01:27:45.560 回答
1

如果您通过“C 中的引用”传递,则需要牢记通过 ->/** 和 * 引用和取消引用。我写的这段代码可能会对你有所帮助

    int delete_node(struct node** head, int target)
    {

        if(*head == NULL)
            return 0;                                                    
    if((*head)->data == target)
        {
            temp = *head;
            *head = (*head)->next;
            free(temp);
            return 1;
        }                                                    
} 

函数调用:

 delete_node(&head, data)

您正在使用直接内存指针操作。您在内存中折腾结构的位置,取消引用它,然后更改该内存位置的值。

于 2013-04-26T01:29:00.543 回答
1

我没有阅读所有细节,但这部分跳出来是不正确的:

(metadata *)ptr - sizeof(metadata)

指针运算以类型为单位完成,而sizeof以字节为单位提供测量值。

所以我怀疑你想说的是:

(metadata *)(((char*)ptr) - sizeof(metadata))

这也对您正在运行的机器做出了一些假设,即metadata可能需要填充以确保字段正确对齐以供此使用。如果sizeof(metadata)不是字长的倍数,这将在很多架构上失败。(但 x86 会让它滑落,尽管会带来性能成本和一些影响,比如原子操作无法在该领域工作。)

于 2013-04-26T01:31:53.207 回答
1

指针是按值传递的。c 中的任何内容都是按值传递的。所以为了改变传递给函数的指针,它应该接收metadata **first.

此外,你应该使用

metadata *strct = ((metadata *)ptr - 1);

因为指针运算是用 sizeof(*p) 的倍数完成的。所以这相当于

metadata *strct = ((metadata *)((char*)ptr - sizeof(metadata)));
于 2013-04-26T01:33:08.023 回答