我在一些我不知道的代码中遇到了这个声明。
typedef struct foo_* foo;
int main(int argc, char** argv)
{
foo a = nullptr; // Ok. foo is a synonym for 'foo_*'
foo_* b = a; // Ok! somehow foo_* is a valid type, but where is it defined?
return 0;
}
先前未定义或声明类型foo_
(这是一个完整的编译示例)。我的理解是typedef
为已经存在的类型提供了同义词,并且在声明或定义之前不能使用类型。由于先前没有声明或定义foo_
,因此typedef
是什么?这是合法的吗?
更新:
有些人说这是可以的,因为typedef中的struct foo_ *被假定为内联前向声明,并且实际上尝试使用foo_将失败。但我刚刚在VS2012上对此进行了测试,并且引用此类型对我来说很好。
答案 0 :(得分:2)
在C ++中:
虽然它可能有点令人困惑,但您可以组合前向声明和类型的使用。
struct foo_;
typedef foo_* foo;
组合:
typedef struct foo_* foo;
在C中,您无法拆分此typedef,因为struct的使用必须包含关键字struct。你也不需要在C中转发声明结构,所以这是通常的语法。
答案 1 :(得分:2)
πάνταῥεῖ的回答是正确的,但我被SO警察强迫添加我自己的答案以提供更全面的背景,而不仅仅是更新问题,所以向πάνταῥεῖ道歉接受这个而不是他的回答。
问题中表单的typedef是下面代码的稍微钝化形式,虽然可以读取和设置指向前向声明类型的指针的值,但指针指向的内存地址无法访问完整的类型定义。
struct A; // Forward declaration, undefined.
int main(int argc, char** argv)
{
A* a; // Ok. Don't need type definition to create a pointer.
a = 0; // Ok. Can set pointer value without definition.
if(*a) // Error. "incomplete type is not allowed".
{} // Without a definition Any attempt to access the pointer is an error.
int* b;
a = b; // Error. "int* cannot be assigned to entity of type A*".
// Even without having seen a definition for A the
// compiler will still enforce type safety.
return 0;
}
在我看到的代码中(在cl_platform_id等的OpenCL C头定义中),似乎正在使用此技术以指定用于在存储的变量中存储ID值的类型class匹配当前环境中的指针类型,但不能将其意外地作为指针访问。
这使人想起Windows头文件中使用的技术,其中void *的类型为HANDLE类型,然后宏用于将具体结构类型的指针定义为不同类型的HANDLES。 OpenCL头文件中使用的技术似乎实现了更强的类型安全性,同时不需要实际定义任何结构类型。
为了最大限度地提高类型安全性而使用前向声明但未定义类型使用技术作为钝的可读性是否值得折衷是一个意见问题,如果不需要C兼容性(因为它是在OpenCL中)然后我希望在C ++中可能有一种更优雅的方式来实现相同的结果,尽管我无法想到一个我的头脑。