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

Meh*_*dad 8 c c++ pointers

为什么是

void foo(T*);
Run Code Online (Sandbox Code Playgroud)

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

void foo(struct T*);
Run Code Online (Sandbox Code Playgroud)

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

Lig*_*ica 5

void foo(struct T*);同时作为struct T该范围内的前向声明,因此命名指向它的指针是安全的.

void foo(T*)那里,没有人知道T应该是什么.如果事实证明它是变量的名称而不是类型,那么代码行就是格式错误的.在可以说代码行有效之前,C++需要更多信息.


pmg*_*pmg 5

在C中,因为指向结构(任何结构)的指针都具有相同的宽度和对齐属性

6.2.5/27(C99标准)

指向void的指针应具有与指向字符类型的指针相同的表示和对齐要求.同样,指向兼容类型的限定或非限定版本的指针应具有相同的表示和对齐要求.所有指向结构类型的指针都应具有相同的表示和对齐要求.所有指向union类型的指针都应具有相同的表示和对齐要求.指向其他类型的指针不需要具有相同的表示或对齐要求.


另一方面,指向任何东西的指针可能具有不同的宽度和/或对齐属性(void*,函数指针,unsigned char*,...)

  • @Tomolak:恰恰相反.这个答案是_only_回答这个问题的答案. (2认同)
  • @Tomalak:问题是,我的问题不是"我的代码为什么不编译?" 但"为什么这样设计C/C++?".你的答案陈述了它没有编译的事实,并说明原因,但它没有说明如果删除限制会出现什么问题 - 另一方面,这个答案解释了问题:不是全部指针在给定平台上可能是相同的,所以编译器只是**不能**生成有效的代码.现在我只想了解编译器是否可以假装它是一个"void*",但答案另外解释了问题的根本原因. (2认同)