代码之家  ›  专栏  ›  技术社区  ›  xtofl Adam Rosenfield

我什么时候不需要typedef?

  •  5
  • xtofl Adam Rosenfield  · 技术社区  · 16 年前

    我遇到一些代码读取

    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; };
    

    是真的吗?您何时需要第一个变体?

    5 回复  |  直到 16 年前
        1
  •  10
  •   Stack Overflow is garbage    16 年前

    首先,这两种声明在C和C++中都是合法的。然而,在C语言中,它们的语义略有不同。(尤其是,您以后引用结构的方式有所不同)。

    要理解的关键概念是,在C中,结构存在于单独的名称空间中。 所有内置类型以及typedef都存在于“默认”命名空间中。也就是说,当我打字的时候 int 编译器只检查这个“默认”名称空间。如果我像在示例中一样键入“tagmystruct”,编译器也只检查这一个名称空间。但根据所使用的声明类型,该结构可能不存在于该命名空间中。

    结构是不同的,并且存在于单独的命名空间中。因此,如果我做出以下声明:

    struct mystruct {};
    

    我可以 简单地称之为“我的停战”。相反,我必须指定我想要存在于结构命名空间中的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;
    

    我们有一个没有名称的结构,它在默认命名空间中被类型化为“tagmystruct”。

    这就是C对待它的方式。这两种类型的声明都有效,但其中一种声明不会在“默认”命名空间中创建别名,因此每次引用该类型时都必须使用struct关键字。

    在C++中,单独的结构命名空间不存在,所以它们意味着同样的事情。(但最好是较短的版本)。

    编辑 只是说清楚,不,C没有名称空间。不是一般意义上的。 C只需将标识符放入两个预定义名称空间中的一个。结构(和枚举,我记得)的名称放在一个中,所有其他标识符放在另一个中。从技术上讲,这些都是命名空间,因为它们是单独的“容器”,在这些容器中放置名称以避免冲突,但它们在C++/C意义上当然不是命名空间。

        2
  •  10
  •   Salman A    16 年前

    如果你要写

    struct MyStruct { int i; double d; };
    

    每当您想要引用该类型时,必须指定您所说的是一个结构:

    struct MyStruct instanceOfMyStruct;
    struct MyStruct *ptrToMyStruct;
    

    对于typedef版本:

    typedef struct { int i; double d; } tagMyStruct;
    

    你只需要写:

    tagMyStruct instanceOfMyStruct;
    tagMyStruct *ptrToMyStruct;
    

    TyPulfEd版本的另一个大优点是,可以在C和C++中以相同的方式引用结构,而在第二个版本中,C引用的结构与C++中的不同。

        3
  •  1
  •   Philip Reynolds    16 年前

    只是速记。

    在第二个实例中,要声明将使用的结构,请执行以下操作:

    struct MyStruct a;
    

    在第一个变体中,您可以使用:

    tagMyStruct a;
    
        4
  •  0
  •   mouviciel    16 年前

    第二种变体也存在于c中。

    您可以在任何时候使用第一个变量来命名您的类型,例如:

    tagEnum myFunc(tagMyStruct * myArg);
    
        5
  •  0
  •   LK.    16 年前

    第一个可能在C++中是不方便的,因为您不能在头文件中声明它。