我目前正在学习 C 并且正在探索如何实现通用二叉树,我偶然发现了这个例子。
我有这个节点结构:
struct node{const char * value; struct node * left; struct node * right;};
typedef struct node node;
这个创建树的函数:
node * create_tree(const void * value, node * left, node * right) {
node * root = malloc(sizeof(node));
if (root) {
root->value=value;
root->left=left;
root->right=right;
}
return root;
}
然后这主要用于:
node * root = create_tree("b", create_tree("a", NULL, NULL), create_tree("c", NULL, NULL));
我明白这是什么结果。我想确保我理解的是内存中“b”、“a”和“c”的最终位置。据我了解,这些等同于 char 指针(因为它们用双引号引起来),因此我的想法是字符 'b' 和 '\0' 存储在堆栈中并从堆中指向。那是实际发生的事情吗?
还有一个问题,因为结构定义采用 void 指针,create_tree 一旦被调用,是否会根据参数类型在堆上分配空间?
回答1
https://en.cppreference.com/w/c/language/string_literal,例如"a"
、"b"
和"c"
,通常存储在只读存储器中。它们不会存储在https://en.wikipedia.org/wiki/Call_stack中。
如果您希望将它们存储在堆栈中,则必须在堆栈上分配一个数组并将字符串文字的内容复制到该数组中。您只是将指针复制到字符串文字并将该指针存储在堆中(由 malloc
分配的内存),而不是堆栈。
您可能将 char
数组与 char *
混淆了。以下是对差异的解释:
int main(void)
{
//This will be stored on the stack, because although it
//is using a string literal for initialization, the
//array itself is declared as a local variable.
char str1[] = "Test";
//This is identical to the previous declaration, except
//for the fact that the length of the array is specified
//explicitly.
char str2[5] = "Test";
//In this case, only the pointer will be stored on the
//stack, but not the string itself, because the pointer
//is pointing to a string literal, which is probably
//stored in read-only memory.
char *str3 = "Test";
}
还有一个问题,因为结构定义采用 void 指针,create_tree 一旦被调用,是否会根据参数类型在堆上分配空间?
函数 create_tree
只知道指针 value
的 value,而不知道它所指向的对象的类型。因此,它无法根据引用对象的类型分配空间。此外,如果您告诉它,它只会在堆上分配空间,例如使用函数 malloc
(您在该函数中调用一次)。