我遇到了一些代码阅读
typedef enum eEnum { c1, c2 } tagEnum; typedef struct { int i; double d; } tagMyStruct;
我听说有传言说这些结构可以追溯到C语言.在C++中你可以很容易地写出来
enum eEnum { c1, c2 }; struct MyStruct { int i; double d; };
真的吗?你什么时候需要第一个变种?
在C中,如果你要写
struct MyStruct { int i; double d; };
无论何时您想引用该类型,您都必须指定您正在讨论结构:
struct MyStruct instanceOfMyStruct; struct MyStruct *ptrToMyStruct;
使用typedef版本:
typedef struct { int i; double d; } tagMyStruct;
你只需要写:
tagMyStruct instanceOfMyStruct; tagMyStruct *ptrToMyStruct;
typedef'd版本的另一大优势是你可以在C和C++中以相同的方式引用结构,而在第二个版本中,它们在C中的含义与在C++中的含义不同.
首先,两个声明在C和C++中都是合法的.但是,在C语言中,它们的语义略有不同.(特别是,您稍后引用结构的方式会有所不同).
要理解的关键概念是,在C中,结构存在于单独的命名空间中.所有内置类型以及typedef都存在于"default"命名空间中.也就是说,当我键入时int
,编译器只检查这个"默认"命名空间.如果我在您的示例中键入"tagMyStruct",编译器也只检查这一个命名空间.但是根据您使用的声明类型,该结构可能不存在于该命名空间中.
结构不同,并且存在于单独的命名空间中.所以,如果我做出以下声明:
struct mystruct {};
我不能简单地将它称为mystruct.相反,我必须指定我想要struct namespace中存在的mystruct:
void foo(struct mystruct bar); // Declare a function which takes a mystruct as its parameter
从长远来看,这有点冗长和尴尬.相反,您可以将其定义为默认命名空间:
typedef struct mystruct mystruct; // From now on, 'mystruct' in the normal namespace is an alias for 'mystruct' in the struct namespace
现在,我的函数可以直接的方式声明:
void foo(mystruct bar);
因此,您的第一个示例只是将这两个步骤合并在一起:声明一个结构,并将一个别名放入常规命名空间.当然,既然我们无论如何都要对它进行类型化,我们不需要"原始"名称,因此我们可以使结构匿名.在宣布之后
typedef struct { int i; double d; } tagMyStruct;
我们有一个没有名称的结构,它在默认名称空间中被"typedef"为"tagMyStruct".
这就是C对待它的方式.两种类型的声明都是有效的,但是没有在"默认"命名空间中创建别名,因此每次引用类型时都必须使用struct关键字.
在C++中,单独的struct命名空间不存在,因此它们的含义相同.(但较短的版本是首选).
编辑只是为了清楚,不,C没有名称空间.不是通常意义上的.C只是将标识符放入两个预定义的命名空间之一.结构(和我记得的枚举)的名称放在一个中,所有其他标识符放在另一个中.从技术上讲,这些是命名空间,因为它们是单独的"容器",其中放置了名称以避免冲突,但它们肯定不是C++/C#意义上的命名空间.