为什么
void foo(T*);
在C和C ++中都是非法的(因为T
未定义),而
void foo(struct T*);
是有效的,即使它仍然没有定义 T
?是否有任何情况会使调用者产生语义差异,T
是结构还是其他类型(class / enum / typedef / etc。)?
答案 0 :(得分:5)
void foo(struct T*);
同时在该范围内充当struct T
的前向声明,因此命名指向它的指针是安全的。
在void foo(T*)
中,没有人知道T
应该是什么。如果事实证明它是变量的名称而不是类型,那么代码行就是格式错误的。在可以说代码行有效之前,C ++需要更多信息。
答案 1 :(得分:5)
在C中,因为指向结构(任何结构)的指针都具有相同的宽度和对齐属性
6.2.5 / 27(C99 Standard)
指向void的指针应具有相同的表示形式 和对齐要求作为指向字符类型的指针。 同样,指向合格或非限定版本的指针 兼容类型应具有相同的表示和 对齐要求。所有指向结构类型的指针 应具有相同的表示和对齐方式 彼此的要求。所有指向联合类型的指针 应具有相同的表示和对齐方式 彼此的要求。指向其他类型的指针需要 没有相同的表示或对齐要求。
另一方面,指向任何东西的指针可能具有不同的宽度和/或对齐属性(void *,函数指针,unsigned char *,...)
答案 2 :(得分:2)
struct T
充当T的forward declaration。您承诺稍后会定义编译器。如果您实际上在T上做了某些事情或尝试实例化它,那么您就会遇到问题:
struct T t1; //error, incomplete type
struct T* t2; // ok
t2->foo // error, incomplete type
只需
T
是任意标识符。它是变量吗?这是一个功能吗?如果不在变量前面添加struct
或class
,该语言就无法转发声明。
答案 3 :(得分:1)
struct T
将T
声明为struct
即使它出现在更大的声明中,即foo
的声明。类型是不完整的,但是当它用于声明指针函数参数时无关紧要。
如果没有struct
,编译器就不知道T
应该是什么。
如果先前已将T
声明为struct
,则在C ++中允许void foo(T*)
但在C中不允许{,因为struct
的名称不会自动变为类型名称,但如果您愿意,可以在C中声明具有相同名称的typedef
。