简体   繁体   English

通过值和引用将c中的结构类型指针传递给函数

[英]passing pointer of struct type in c to a function by value and by reference

okay, I know for a fact that passing pointer to a structure as argument to a function makes the argument behave as though it was passed by value, just for the special case of structures. 好的,我知道这样一个事实,即仅针对结构的特殊情况,将指向结构的指针作为函数的参数传递会使该参数的行为就好像它是通过值传递的。 So if I were to make any modifications to head ptr in the link list, the changes made in the called function wouldn't be reflected in the calling fnt., but my question is whether changes made to any subsequent node's pointer in the called function is reflected in the calling function..for example , if I were to say delete the fifth node from the beginning of a link list whose head pointer i passed by using single pointer instead of double pointer,would the list returned from the function contain the deleted element or would it not contain it? 因此,如果我要对链接列表中的head ptr进行任何修改,则在调用函数中不会反映对被调用函数所做的更改。但是我的问题是,是否对被调用函数中的任何后续节点的指针进行了更改反映在调用函数中。例如,如果我说要从链接列表的开头删除第五个节点,该链接列表的头指针我是通过使用单指针而不是双指针传递的,那么从函数返回的列表是否包含删除的元素或将不包含它?

ok another example: in the following code to recursively delete alternate elements in a link list, wouldnt it fail, because the parameter is *head instead of **head? 另一个例子:在下面的代码中递归删除链接列表中的备用元素,它不会失败,因为参数是* head而不是** head?

void deleteAlt(struct node *head)
{
  if (head == NULL)
    return;

  struct node *node = head->next;

  if (node == NULL)
    return;

  /* Change the next link of head */
  head->next = node->next;   

  /* free memory allocated for node */
  free(node);

  /* Recursively call for the new next of head */
  deleteAlt(head->next);
}

I know for a fact that passing pointer to a structure as argument to a function makes the argument behave as though it was passed by value, just for the special case of structures. 我知道这样一个事实:仅针对结构的特殊情况,将指向结构的指针作为函数的参数传递会使该参数的行为就像通过值传递一样。

That's simply not true. 那根本不是真的。 The pointer itself if passed by value (as every argument is in C), but the variable referenced by the pointer isn't copied. 指针本身(如果按值)传递(因为每个参数都在C中),但是不会复制指针所引用的变量。 Changing it in the function will change it in the caller since it's the same structure. 在函数中更改它会在调用方中更改它,因为它的结构相同。

#include <stdio.h>
#include <stdlib.h>

struct S {
   int i;
};

void f(struct S* s) {
   s->i = 456;
}

int main() {
   struct S* s = malloc(sizeof(struct S));
   s->i = 123;
   printf("%d\n", s->i);
   f(s);
   printf("%d\n", s->i);
   free(s);
   return 0;
}

$ gcc -o a a.c && a
123
456

ok another example: in the following code to recursively delete alternate elements in a link list, wouldnt it fail, because the parameter is *head instead of **head ? 另一个例子:在下面的代码中递归删除链接列表中的备用元素,它不会失败,因为参数是*head而不是**head

No. Since deleteAlt never modifies head , there's no need to update its caller's head , so there's no need to pass a pointer to the caller's head . 不会。由于deleteAlt永远不会修改head ,因此无需更新其调用方的head ,因此无需将指针传递给调用方的head

Pointers to structures passed by value behaving as entire structures being passed by value is obviously not true. 指向按值传递的结构的指针显然正确,因为按值传递的整个结构是正确的。

By the way, C doesn't have "pass by reference". 顺便说一句,C 没有 “按引用传递”。 You can pass the pointer to something, but then that happens by value. 您可以将指针传递的东西,但随后出现这种情况的值。

If you passed a pointer to the link list and modified it (deleted an element) the value you removed would be removed in the context of the caller. 如果将指针传递给链接列表并对其进行了修改(删除了元素),则删除的值将在调用方的上下文中删除。

The very simplest reason they would need (struct node ** head) is because to modify something you need its address. 他们需要的最简单的原因(结构节点**头)是因为要修改某些内容,您需要它的地址。 If you are going to delete something (*head in this case) you are going to need its address. 如果要删除某些内容(在这种情况下为* head),则需要其地址。 Anything that you want to modify you need its address. 您要修改的任何内容都需要其地址。

To delete a node, you have to redirect the next pointer of the previous node to point to the next node instead of the current one. 要删除一个节点,您必须重定向上一个节点的下一个指针,使其指向下一个节点而不是当前节点。 Since we don't have a pointer to the previous node, we can't redirect its next pointer. 由于我们没有指向上一个节点的指针,因此无法重定向其下一个指针。 So what do we do? 那么我们该怎么办?

We can easily get away by moving the data from the next node into the current node and then deleting the next node. 通过将数据从下一个节点移到当前节点,然后删除下一个节点,我们可以轻松地逃脱。

This solution has O(1) runtime. 该解决方案具有O(1)运行时。 Here's some code to illustrate this simple logic. 这里有一些代码来说明这种简单的逻辑。

void deleteNode( Node * node )
{
    Node * temp = node->next;
    node->data = node->next->data;
    node->next = temp->next;
   free(temp);
}

Some things to consider. 一些事情要考虑。

This method could pose potential problems. 此方法可能会带来潜在的问题。

For instance, let's consider we have a linked list A -> B -> C -> D and we are given a pointer to B to delete it. 例如,让我们考虑一下,我们有一个链表A-> B-> C-> D,并且我们得到了指向B的指针以将其删除。

Theoretically, you would expect B to be deleted and all pointers which were pointing to   B to become invalid.

However, if we use this function to delete B, all pointers which were pointing to B will still be valid. Furthermore, node B now will contain the value C and node C will be invalid.

Any previous pointers to C will become invalid, which may not be expected behavior in general. This is not a problem if there are no external links to any of the items in the linked list.

But this would definitely be something you should consider asking your interviewer to show your thinking process. 但这绝对是您应该考虑要求面试官展示您的思维过程的事情。

For proper understanding working of deleting an element from the linklist please refer following link :

https://www.cs.bu.edu/teaching/c/linked-list/delete/ https://www.cs.bu.edu/teaching/c/linked-list/delete/

Pointers are address variables ie they contains addresses, so if a pointer is passed to a function , you are passing the actual value itself. 指针是地址变量,即它们包含地址,因此,如果将指针传递给函数,则您将传递实际值本身。

On performing any action on it , that value will be modified. 在对其执行任何操作时,该值将被修改。 In your case it will be deleted. 您的情况将被删除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM