我使用gcc编译器编译了以下c代码:
#include <stdio.h>
struct node{
int info;
struct test* next;
};
int main()
{
struct node start;
struct node* p;
start.info = 2;
start.next = (struct test*)&start;
printf("start.next = %p \n",start.next);
p = start.next;
printf("p->info = %d\n",p->info);
}
但令我惊讶的是,在声明next
(在structure node
中)作为指向未声明类型(struct test
)的指针后,仍然编译成功!编制完上述程序后,其打印仅发出如下警告:
test.c:15:4: warning: assignment from incompatible pointer type [enabled by default]
p = start.next;
^
现在我怀疑为什么编译器没有因为没有声明structure test
而产生错误?
答案 0 :(得分:6)
程序中没有未定义的类型。在结构struct test
中声明了一个不完整的类型struct node
。
您可以使用指向不完整类型的指针。
考虑一个简化的例子
会更清楚struct node{
int info;
struct node* next;
};
在此结构中,指针next也指向不完整类型struct node
,因为结构定义仅在结束括号后完成。
一个更有趣的例子。类型void *
在C程序中非常常用。但是根据C标准(6.2.5类型,第19页)
19 void类型包含一组空值; 它是一个 不完整的对象类型,无法完成。
至于指针本身(C标准,6.2.5类型,第21页)
A pointer type is a complete object type.
关于结构本身(6.7.2.1结构和联合说明符,第8页)
8中存在一个struct-declaration-list struct-or-union-specifier在转换中声明一个新类型 单元。 struct-declaration-list是一系列声明 结构或联盟的成员。如果是struct-declaration-list 不包含命名成员,没有匿名结构,也没有匿名 工会,行为是不确定的。 类型不完整,直到 在终止列表的}之后立即完成 此后强>
答案 1 :(得分:1)
来自cppreference的explicit type conversion部分:
此外,允许使用C风格的演员表格来演绎,演奏和演奏 指向不完整类类型的指针之间。如果表达和 new_type是指向不完整类类型的指针,它未指定 是否选择了static_cast或reinterpret_cast。
struct test*
是指向不完整类型的指针。 struct test
是一个前向声明,被引入到main的本地范围。