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



为什么

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

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

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

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

如果T之前被声明为struct,那么void foo(T*)在c++中是允许的,但在C中不允许,因为struct的名字不会自动成为类型名,尽管你可以在C中用相同的名字声明typedef

最新更新