为什么指向未定义结构的指针有时在C和C ++中是非法的

时间:2011-05-03 21:48:04

标签: c++ c pointers

为什么

void foo(T*);

在C和C ++中都是非法的(因为T未定义),而

void foo(struct T*);

是有效的,即使它仍然没有定义 T?是否有任何情况会使调用者产生语义差异,T是结构还是其他类型(class / enum / typedef / etc。)?

4 个答案:

答案 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

是任意标识符。它是变量吗?这是一个功能吗?如果不在变量前面添加structclass,该语言就无法转发声明。

答案 3 :(得分:1)

struct TT声明为struct即使它出现在更大的声明中,即foo的声明。类型是不完整的,但是当它用于声明指针函数参数时无关紧要。

如果没有struct,编译器就不知道T应该是什么。

如果先前已将T声明为struct,则在C ++中允许void foo(T*)但在C中不允许{,因为struct的名称不会自动变为类型名称,但如果您愿意,可以在C中声​​明具有相同名称的typedef