C: error: incompatible pointer types, remove & - a pointer to store its own address
C: error: incompatible pointer types, remove & - a pointer to store its own address
初学者问题:我想我有点理解指针(int *p,x = 1,p = &x),但显然不理解“->”和结构。
typedef struct node
{
bool is_word;
struct node* children[27];
}
node;
和
node* root = calloc(1, sizeof(node));
printf("address:%p\n", &root->children[1]);
printf("content%p\n", root->children[1]);
printf("\n");
root->children[1] = &root->children[1];
printf("address:%p\n", &root->children[1]);
printf("content%p\n", root->children[1]);
很简单,我有一个指针,我想让它存放自己的地址。但它给了我:
error: incompatible pointer types assigning to 'struct node *'
from 'struct node **'; remove & [-Werror,-Wincompatible-pointer-types]
root->children[1] = &root->children[1];
^ ~~~~~~~~~~~~~~~~~~
我尝试了一些组合,none 目前有效。我错过了什么?
改变
root->children[1] = &root->children[1];
至
root->children[1] = root->children[1];
它不起作用的原因与错误消息中所述完全相同 -
root->children[i]
是node*类型,也就是说root->children[i]本身就是一个内存地址,指向struct node
.
类型的数据
话虽这么说,为什么要存储内存地址?
考虑以下示例:您是一个指向类型 int:
的指针
int *ptr
现在,如果你想要 ptr 的内存地址,你可以 printf("%p", ptr)
如果你想要数据,只需 printf("%d", *ptr)
根据您对 Ishay 的回答的评论,您想要实现 content == address...
很容易得到它,但我想警告你为什么不应该这样做。如果 node->children[1]
指向它自己的地址,取消引用指针是未定义的行为,因为那里是 而不是 一个 node
而是一个 node *
。这意味着一旦你有了它,任何对 *(node->children[1])
的访问,无论是读还是写,甚至使用 node->children[1]->...
语法,根据严格的别名规则(搜索 SO for C strict aliasing rule 以获得更多详细信息)。
一旦你被警告过,C语言对程序员是非常有信心的,甚至允许你做无意义的事情:
root->children[1] = (void *) &root->children[1]; /* or root->children[1] = (node *) &root->children[1]; */
printf("address:%p\n", &root->children[1]);
printf("content%p\n", root->children[1]);
会显示你想要的。这是因为总是允许将指针复制到 (void *)
,同样,void *
可以复制到任何其他指针。 C 标准要求(假设没有对齐问题,并且在您的示例中不应该存在)那些指针赋值是完美定义的,并且:
node ** p = (node **) root->children[1];
也已定义,p
必须指向 root->children[1]
。换句话说,您可以将指向一种类型的指针转换为指向另一种类型的指针,然后将其转换回来将为您提供初始值,但您绝不能取消引用不正确指针。
初学者问题:我想我有点理解指针(int *p,x = 1,p = &x),但显然不理解“->”和结构。
typedef struct node
{
bool is_word;
struct node* children[27];
}
node;
和
node* root = calloc(1, sizeof(node));
printf("address:%p\n", &root->children[1]);
printf("content%p\n", root->children[1]);
printf("\n");
root->children[1] = &root->children[1];
printf("address:%p\n", &root->children[1]);
printf("content%p\n", root->children[1]);
很简单,我有一个指针,我想让它存放自己的地址。但它给了我:
error: incompatible pointer types assigning to 'struct node *'
from 'struct node **'; remove & [-Werror,-Wincompatible-pointer-types]
root->children[1] = &root->children[1];
^ ~~~~~~~~~~~~~~~~~~
我尝试了一些组合,none 目前有效。我错过了什么?
改变
root->children[1] = &root->children[1];
至
root->children[1] = root->children[1];
它不起作用的原因与错误消息中所述完全相同 -
root->children[i]
是node*类型,也就是说root->children[i]本身就是一个内存地址,指向struct node
.
话虽这么说,为什么要存储内存地址?
考虑以下示例:您是一个指向类型 int:
的指针
int *ptr
现在,如果你想要 ptr 的内存地址,你可以 printf("%p", ptr)
如果你想要数据,只需 printf("%d", *ptr)
根据您对 Ishay 的回答的评论,您想要实现 content == address...
很容易得到它,但我想警告你为什么不应该这样做。如果 node->children[1]
指向它自己的地址,取消引用指针是未定义的行为,因为那里是 而不是 一个 node
而是一个 node *
。这意味着一旦你有了它,任何对 *(node->children[1])
的访问,无论是读还是写,甚至使用 node->children[1]->...
语法,根据严格的别名规则(搜索 SO for C strict aliasing rule 以获得更多详细信息)。
一旦你被警告过,C语言对程序员是非常有信心的,甚至允许你做无意义的事情:
root->children[1] = (void *) &root->children[1]; /* or root->children[1] = (node *) &root->children[1]; */
printf("address:%p\n", &root->children[1]);
printf("content%p\n", root->children[1]);
会显示你想要的。这是因为总是允许将指针复制到 (void *)
,同样,void *
可以复制到任何其他指针。 C 标准要求(假设没有对齐问题,并且在您的示例中不应该存在)那些指针赋值是完美定义的,并且:
node ** p = (node **) root->children[1];
也已定义,p
必须指向 root->children[1]
。换句话说,您可以将指向一种类型的指针转换为指向另一种类型的指针,然后将其转换回来将为您提供初始值,但您绝不能取消引用不正确指针。