![](/img/trans.png)
[英]Why Does This Kind of Pointer Arithmetic Work In A Function, But Not In Main?
[英]Why does this pointer arithmetic not work?
在我的程序中,我有一個二進制樹,其定義如下:
struct node {
char value;
struct node *left, *right;
};
在我的程序中,我試圖編寫一個函數,該函數以索引順序(從上到下,從右到左遍歷)返回每個節點值的字符串。
為此,我編寫了以下函數:
char *to_string_util(struct node *root, char *str) {
if (!root) return str;
*str++ = root->value;
// If not NULL
if (root->left) to_string_util(root->left, str);
if (root->right) to_string_util(root->right, str);
return str;
}
這似乎應該可以工作,但是可惜沒有。 我已經通過使用數組索引來使其工作了,該方法可以工作,但是不理想,因為它需要引入另一個變量。
這是有效的版本:
char *to_string_util(struct node *root, char *str, int *cur_pos) {
if (!root) return str;
str[(*cur_pos)++] = root->value;
if (root->left) to_string_util(root->left, str, cur_pos);
if (root->right) to_string_util(root->right, str, cur_pos);
return str;
}
給定樹:
+
/ \
* *
/ \ / \
a a b b
結果應為: +*aa*bb
需要注意的一件事是,我在另一個函數中調用了此函數,該函數在其末尾附加了一個空字符,這不應影響輸出,但我認為可能值得一提。
為什么使用數組索引的第二個版本有效,而第一個無效?
它不起作用,因為您忽略了遞歸子調用返回的str
的新值。 您的函數旨在通過執行return str;
來更新str
的值並返回新值return str;
。 您只是丟棄返回的值。 因此,在每個遞歸級別,對右子樹的調用都會覆蓋由遞歸調用寫入左子樹的數據。
這可能更接近您的想法
// If not NULL
if (root->left) str = to_string_util(root->left, str);
if (root->right) str = to_string_util(root->right, str);
而且,當然,您應該記住最后要對字符串進行零終止。
如果您的功能以
if (!root) return str;
那么遞歸子調用實際上就不需要空檢查,可以簡化為
str = to_string_util(root->left, str);
str = to_string_util(root->right, str);
(除非您將其視為優化)。
您基於索引的版本不再依賴於str
的更新(並且完全不會更新)。 這取決於位置值*cur_pos
的更新。 由於位置值是通過引用在不同遞歸級別之間傳遞的,因此所有遞歸級別都可以查看這些更新。
您也可以在第一個版本中使用相同的技術,即通過reference傳遞指針值。 但是為此,您必須將str
作為char **str
(指針到指針)傳遞,並使用*str
和當前字符指針。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.