为什么
void foo(T*);
在C和c++中都是非法的(因为T
是未定义的),而
void foo(struct T*);
是有效的,即使它仍然没有定义 T
?是否有任何情况下,它使一个语义差异的调用者是否T
是一个结构或其他类型(类/enum/typedef/等)?
void foo(struct T*);
同时在该范围内作为struct T
的前向声明,因此命名指向它的指针是安全的。
在void foo(T*)
中没有告诉T
应该是什么。如果结果是变量名而不是类型名,那么这行代码格式错误。c++需要更多的信息才能判断这行代码是否有效。
在C语言中,因为指向结构体(任何结构体)的指针都有相同的宽度和对齐属性
6.2.5/27 (C99标准)指向void的指针应具有相同的表示和对齐要求作为指向字符类型的指针。的限定或非限定版本的指针兼容的类型应具有相同的表示和校准需求。所有指向结构类型的指针应具有相同的表示和排列方式需求彼此一致。所有指向联合类型的指针应具有相同的表示和排列方式需求彼此一致。指向其他类型的指针需要没有相同的表示或对齐要求。
另一方面,指向任何对象的指针可以有不同的宽度和/或对齐属性(void*,函数指针,unsigned char*,…)
struct T
充当t的前向声明。您向编译器承诺稍后将定义它。如果你在T上做了一些事情或者试图实例化它,你就会遇到问题:
struct T t1; //error, incomplete type
struct T* t2; // ok
t2->foo // error, incomplete type
T
是一个任意标识符。它是一个变量吗?它是一个函数吗?如果不在变量前添加struct
或class
,该语言无法提供转发声明的功能。
struct T
将T
声明为struct
,即使它出现在更大的声明中,即foo
的声明。该类型是不完整的,但当它用于声明指针函数形参时,这无关紧要。
没有struct
,编译器不知道T
应该是什么。
如果T
之前被声明为struct
,那么void foo(T*)
在c++中是允许的,但在C中不允许,因为struct
的名字不会自动成为类型名,尽管你可以在C中用相同的名字声明typedef
。