[英]When don't I need a typedef?
我遇到了一些代码阅读
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#意义上的命名空间。
这只是速记。
在第二个实例中,要使用以下命令声明结构:
struct MyStruct a;
在第一个版本中,您可以这样做:
tagMyStruct a;
第二个变体也存在于C.
只要您想为类型命名,就可以使用第一个变体,例如:
tagEnum myFunc(tagMyStruct * myArg);
第一个可能在C ++中不方便,因为您无法在头文件中转发声明它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.