你如何传递C中的结构指针?

问题描述:

我有点困惑于如何通过引用传递函数指针?你如何传递C中的结构指针?

举例来说,这里的一些代码,我已经写了 (我没有复制整个功能,只是它的一部分是相关的)

metadata * removeBlock(metadata *first) 
{ 

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

我要的是,当函数返回,传入的原始值应该设置为NULL。 这里是我如何调用函数,(这行代码将从堆中的区域中拉出元数据结构,它工作正常,我已经调试并确保在此之后,结构实际上指向有效的元数据结构)

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

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

谢谢。

+1

C根本没有'传递引用',它只有'传值'。即使在传递指针时,它本质上也是'传递值'。 – 2013-04-26 01:22:52

+1

您的功能有问题。例如,如果'first == NULL',那么继续并尝试设置'first-> in_use'来解引用NULL指针。 – Blastfurnace 2013-04-26 01:25:55

+0

我没有任何情况下,当用户传入一个NULL,虽然这是一个好主意,以消除检查,以便它永远不会发生。谢谢。 – iamseiko 2013-04-26 01:38:45

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

无论如何,你会想要一个指针到一个指针,像这样:

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); 
+1

这是怎么回事?不是'first = NULL',其中'first'是与'* first = NULL'相同的指针,其中'first'是指向指针的指针? – 2013-04-26 01:32:46

+0

我尝试使用像你说的双指针,它完全按照它应该做的。谢谢。 – iamseiko 2013-04-26 01:33:11

+1

@SheerFish不,它更深一层。 '* first = NULL'其中'first'是一个指向指针的指针,它保持原来的状态。它是指向*的东西(这也是一个指针)。 – 2013-04-26 01:41:18

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

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

这是一个指针传递ptr为变量的值(从不介意那个数值的指针),使功能与*ptr原值玩。这种技术有时被称为传递地址,并且是最靠近的C必须通过引用。

+0

谢谢,我做到了,它工作。 – iamseiko 2013-04-26 01:35:08

如果您通过'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) 

你与直接内存指针操作工作。你在内存中抛出结构的位置,引用它,然后改变该内存位置的值。

+0

这个'delete_node'从哪里来? (不是我的投票) – Shoe 2013-04-26 01:30:22

+1

我更新它来纠正这一点。忘了说明这是底层的函数调用。这只是我为C链接列表编写的示例代码片段。 – TheCodingArt 2013-04-26 01:33:02

+0

我的数据不是一个整数,这是一个双向链表的一部分,没有任何数据。它只是位于堆中的位置引用,位于数据块旁边,因此不会删除任何要删除的数据。但是,正如你所建议的那样,使用双指针起作用。谢谢。 – iamseiko 2013-04-26 01:34:49

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

(metadata *)ptr - sizeof(metadata) 

指针运算的类型的单位进行,而sizeof为您提供测量以字节为单位。

所以我怀疑你想要说的是:

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

这也使得有关你的机器上运行,即一些假设可能需要填充metadata以确保字段正确对齐以供此用途。如果sizeof(metadata)不是字大小的倍数,则在很多体系结构上都会失败。 (但是x86会让它滑动,尽管性能成本和原子操作在某些领域不起作用)。

+0

为什么不''(元数据*)ptr - 1'? – Elazar 2013-04-26 01:34:23

+0

@Elazar - 第一个问题:应该是一样的,但我想要更明确一些。第二个问题:它绝对不是*无关紧要的事情,编译器不保证以你的名义添加任何填充。 – asveikau 2013-04-26 01:36:44

+0

不完全。在我的堆中,元数据结构停留在数据块旁边的堆中。所以,当用户参考该数据块时,我试图通过减去大小来找到该元数据结构。它的工作原理,我没有专门投它,但我想你的方式更合理和万无一失。 – iamseiko 2013-04-26 01:37:06

指针按值传递。 任何东西在c是通过值。所以为了改变传递给函数的指针,它应该得到metadata **first

此外,你应该使用

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

为指针运算用的sizeof(* P)的整数倍进行。所以这相当于

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