什么时候不需要typedef?

时间:2022-09-20 13:54:48

I encountered some code reading

我遇到了一些代码阅读

typedef enum eEnum { c1, c2 } tagEnum;

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

I heard rumours that these constructs date from C. In C++ you can easily write

我听说有传言说这些结构是从C语言开始的。在C ++中你可以很容易地写出来

enum eEnum { c1, c2 };
struct MyStruct { int i; double d; };

Is that true? When do you need the first variant?

真的吗?你什么时候需要第一个变种?

5 个解决方案

#1


First, both declarations are legal in both C and C++. However, in C, they have slightly different semantics. (In particular, the way you refer to the struct later varies).

首先,两个声明在C和C ++中都是合法的。但是,在C语言中,它们的语义略有不同。 (特别是,您稍后引用结构的方式会有所不同)。

The key concept to understand is that in C, structs exist in a separate namespace. All built-in types, as well as typedefs exist in the "default" namespace. That is, when I type int, the compiler only checks this "default" namespace. If I type "tagMyStruct" as in your example, the compiler also only checks this one namespace. But depending which type of declaration you use, the struct may not exist in that namespace.

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

Structs are different, and exist in a separate namespace. So if I make the following declaration:

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

struct mystruct {};

I can not simply refer to it as mystruct. Instead, I have to specify that I want the mystruct which exists in the struct namespace:

我不能简单地将它称为mystruct。相反,我必须指定我想要struct namespace中存在的mystruct:

void foo(struct mystruct bar); // Declare a function which takes a mystruct as its parameter

Which gets a bit verbose and awkward in the long run. Instead, you can typedef it into the default namespace:

从长远来看,这有点冗长和尴尬。相反,您可以将其定义为默认命名空间:

typedef struct mystruct mystruct; // From now on, 'mystruct' in the normal namespace is an alias for 'mystruct' in the struct namespace

and now, my function can be declared in the straightforward way:

现在,我的函数可以直接的方式声明:

void foo(mystruct bar);

So your first example simply merges these two steps together: Declare a struct, and put an alias into the regular namespace. And of course, since we're typedeffing it anyway, we don't need the "original" name, so we can make the struct anonymous. So after your declaration

因此,您的第一个示例只是将这两个步骤合并在一起:声明一个结构,并将一个别名放入常规命名空间。当然,既然我们正在对它进行类型化,我们不需要“原始”名称,因此我们可以使结构匿名。在宣布之后

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

we have a struct with no name, which has been typedef'ed to 'tagMyStruct' in the default namespace.

我们有一个没有名称的结构,它在默认名称空间中被“typedef”为“tagMyStruct”。

That's how C treats it. Both types of declarations are valid, but one does not create the alias in the "default" namespace, so you have to use the struct keyword every time you refer to the type.

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

In C++, the separate struct namespace doesn't exist, so they mean the same thing. (but the shorter version is preferred).

在C ++中,单独的struct命名空间不存在,因此它们的含义相同。 (但较短的版本是首选)。

Edit Just to be clear, no, C does not have namespaces. Not in the usual sense. C simply places identifiers into one of two predefined namespaces. The names of structs (and enums, as I recall) are placed in one, and all other identifiers in another. Technically, these are namespaces because they are separate "containers" in which names are placed to avoid conflicts, but they are certainly not namespaces in the C++/C# sense.

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

#2


In C, if you were to write

在C中,如果你要写

struct MyStruct { int i; double d; };

whenever you wanted to reference that type, you'd have to specify that you were talking about a struct:

无论何时您想引用该类型,您都必须指定您正在讨论结构:

struct MyStruct instanceOfMyStruct;
struct MyStruct *ptrToMyStruct;

With the typedef version:

使用typedef版本:

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

you only have to write:

你只需要写:

tagMyStruct instanceOfMyStruct;
tagMyStruct *ptrToMyStruct;

The other big advantage with the typedef'd version is that you can refer to the struct the same way in both C and C++, whereas in the second version they are refered to differently in C than in C++.

typedef'd版本的另一大优势是你可以在C和C ++中以相同的方式引用结构,而在第二个版本中,它们在C中的含义与在C ++中的含义不同。

#3


It's just shorthand.

这只是速记。

In the second instance, to declare the struct you'd do so with:

在第二个实例中,要使用以下命令声明结构:

struct MyStruct a;

In the first variant, you'd do so with:

在第一个版本中,您可以这样做:

tagMyStruct a;

#4


The second variant also exists in C.

第二个变体也存在于C.

You use the first variant whenever you want to name your type, e.g.:

只要您想为类型命名,就可以使用第一个变体,例如:

tagEnum myFunc(tagMyStruct * myArg);

#5


The first one may be inconvenient in C++, as you cannot forward declare it in a header file.

第一个可能在C ++中不方便,因为您无法在头文件中转发声明它。

#1


First, both declarations are legal in both C and C++. However, in C, they have slightly different semantics. (In particular, the way you refer to the struct later varies).

首先,两个声明在C和C ++中都是合法的。但是,在C语言中,它们的语义略有不同。 (特别是,您稍后引用结构的方式会有所不同)。

The key concept to understand is that in C, structs exist in a separate namespace. All built-in types, as well as typedefs exist in the "default" namespace. That is, when I type int, the compiler only checks this "default" namespace. If I type "tagMyStruct" as in your example, the compiler also only checks this one namespace. But depending which type of declaration you use, the struct may not exist in that namespace.

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

Structs are different, and exist in a separate namespace. So if I make the following declaration:

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

struct mystruct {};

I can not simply refer to it as mystruct. Instead, I have to specify that I want the mystruct which exists in the struct namespace:

我不能简单地将它称为mystruct。相反,我必须指定我想要struct namespace中存在的mystruct:

void foo(struct mystruct bar); // Declare a function which takes a mystruct as its parameter

Which gets a bit verbose and awkward in the long run. Instead, you can typedef it into the default namespace:

从长远来看,这有点冗长和尴尬。相反,您可以将其定义为默认命名空间:

typedef struct mystruct mystruct; // From now on, 'mystruct' in the normal namespace is an alias for 'mystruct' in the struct namespace

and now, my function can be declared in the straightforward way:

现在,我的函数可以直接的方式声明:

void foo(mystruct bar);

So your first example simply merges these two steps together: Declare a struct, and put an alias into the regular namespace. And of course, since we're typedeffing it anyway, we don't need the "original" name, so we can make the struct anonymous. So after your declaration

因此,您的第一个示例只是将这两个步骤合并在一起:声明一个结构,并将一个别名放入常规命名空间。当然,既然我们正在对它进行类型化,我们不需要“原始”名称,因此我们可以使结构匿名。在宣布之后

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

we have a struct with no name, which has been typedef'ed to 'tagMyStruct' in the default namespace.

我们有一个没有名称的结构,它在默认名称空间中被“typedef”为“tagMyStruct”。

That's how C treats it. Both types of declarations are valid, but one does not create the alias in the "default" namespace, so you have to use the struct keyword every time you refer to the type.

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

In C++, the separate struct namespace doesn't exist, so they mean the same thing. (but the shorter version is preferred).

在C ++中,单独的struct命名空间不存在,因此它们的含义相同。 (但较短的版本是首选)。

Edit Just to be clear, no, C does not have namespaces. Not in the usual sense. C simply places identifiers into one of two predefined namespaces. The names of structs (and enums, as I recall) are placed in one, and all other identifiers in another. Technically, these are namespaces because they are separate "containers" in which names are placed to avoid conflicts, but they are certainly not namespaces in the C++/C# sense.

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

#2


In C, if you were to write

在C中,如果你要写

struct MyStruct { int i; double d; };

whenever you wanted to reference that type, you'd have to specify that you were talking about a struct:

无论何时您想引用该类型,您都必须指定您正在讨论结构:

struct MyStruct instanceOfMyStruct;
struct MyStruct *ptrToMyStruct;

With the typedef version:

使用typedef版本:

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

you only have to write:

你只需要写:

tagMyStruct instanceOfMyStruct;
tagMyStruct *ptrToMyStruct;

The other big advantage with the typedef'd version is that you can refer to the struct the same way in both C and C++, whereas in the second version they are refered to differently in C than in C++.

typedef'd版本的另一大优势是你可以在C和C ++中以相同的方式引用结构,而在第二个版本中,它们在C中的含义与在C ++中的含义不同。

#3


It's just shorthand.

这只是速记。

In the second instance, to declare the struct you'd do so with:

在第二个实例中,要使用以下命令声明结构:

struct MyStruct a;

In the first variant, you'd do so with:

在第一个版本中,您可以这样做:

tagMyStruct a;

#4


The second variant also exists in C.

第二个变体也存在于C.

You use the first variant whenever you want to name your type, e.g.:

只要您想为类型命名,就可以使用第一个变体,例如:

tagEnum myFunc(tagMyStruct * myArg);

#5


The first one may be inconvenient in C++, as you cannot forward declare it in a header file.

第一个可能在C ++中不方便,因为您无法在头文件中转发声明它。