[英]When must a function receive an argument by reference in order to change something about the argument?
我的問題與以下代碼有關(請注意,我在此處詢問了有關代碼不同區域的相關問題):
#include <stdio.h>
#include <stdlib.h>
struct node
{
int v;
struct node * left;
struct node * right;
};
typedef struct node Node;
struct bst
{
Node * root;
};
typedef struct bst BST;
BST * bst_insert(BST * tree, int newValue);
Node * bst_insert_node(Node * node, int newValue);
void bst_traverseInOrder(BST * tree);
void bst_traverseInOrderNode(Node * node);
int main(void)
{
BST * t = NULL;
t = bst_insert(t, 5);
bst_insert(t, 8);
bst_insert(t, 6);
bst_insert(t, 3);
bst_insert(t, 12);
bst_traverseInOrder(t);
return 0;
}
BST * bst_insert(BST * tree, int newValue)
{
if (tree == NULL)
{
tree = (BST *) malloc(sizeof(BST));
tree->root = (Node *) malloc(sizeof(Node));
tree->root->v = newValue;
tree->root->left = NULL;
tree->root->right = NULL;
return tree;
}
tree->root = bst_insert_node(tree->root, newValue);
return tree;
}
Node * bst_insert_node(Node * node, int newValue)
{
if (node == NULL)
{
Node * new = (Node *) malloc(sizeof(Node));
new->v = newValue;
new->left = NULL;
new->right = NULL;
return new;
}
else if (newValue < node->v)
node->left = bst_insert_node(node->left, newValue);
else
node->right = bst_insert_node(node->right, newValue);
return node;
}
void bst_traverseInOrder(BST * tree)
{
if (tree == NULL)
return;
else
{
bst_traverseInOrderNode(tree->root);
printf("\n");
}
}
void bst_traverseInOrderNode(Node * node)
{
if (node == NULL)
return;
else
{
bst_traverseInOrderNode(node->left);
printf("%d ", node->v);
bst_traverseInOrderNode(node->right);
}
}
特別是,看來我必須重新分配t
到bst-insert(t, 5)
在main
以實際修改t
本身,因為bst_insert不采取BST *
參照,但只能通過值(例如所以它永遠不能真正更改BST *
本身)。 但是,稍后,當創建了BST時,我可以簡單地聲明bst_insert(t, 8)
,這將更改t
本身(例如,更改t->root->left
),即使它沒有接收到t
作為參數參考。 有人可以在這里給我解釋一下區別嗎? 非常感謝!
“ ...因為bst_insert不會通過引用來獲取BST *,而僅通過值來獲取。”您使用了錯誤的術語,這可能是由於對下面概念的不清楚理解。
C沒有按引用傳遞 :函數的每個參數都按值傳遞。 傳遞值意味着在進行函數調用時,將復制參數,並且函數的相應參數將獲得該副本。 因此,在函數內部,您可以使用參數的副本。
相反,某些語言(特別是C ++,但不是C )可以通過引用傳遞參數。 這意味着函數中的相應參數將成為參數的別名 ,即可以用作同一對象的替代名稱。 在這種情況下,您使用函數內部的別名對對象進行的任何修改都會影響函數“外部”的參數。
在C語言中,您可以使用指針作為函數參數來更接近傳遞引用的行為。 如果傳遞指針值 (即對象地址),則可以在函數內部使用它來間接更改指針指向的對象。
有人將此稱為“技巧” 傳遞指針 (或“ 呼叫 傳遞 指針” ),但IMO將此術語誤導給不了解實際底層機制的初學者。 確實,這根本不是一種新機制,它只是應用於指針值的按值傳遞! 實際上,您對指針本身 (相對於所指向的對象)所做的任何更改都是本地的,即不會影響您在調用中傳遞的實際指針。
不同之處在於,在第一次調用中(當t
為NULL
),函數bst_insert
更改了指針t
本身(它使用malloc
將新值分配給t
)。 在接下來的調用中, t
本身不會被修改,只會修改它所指向的內容。 例如,改變t->root
指cahnge由指向的內容t
,但不t
本身(地址它指向)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.