我在现有代码库中有以下(工作)代码,在C和C ++之间共享的包含文件中使用,在MSVC(2010)和Windows DDK上编译:
struct X {
USHORT x;
} typedef X, *PX;
和
enum MY_ENUM {
enum_item_1,
enum_item_2
} typedef MY_ENUM;
据我所知,正确的定义应如下所示:
typedef struct {
USHORT x;
} X, *PX;
以下表格是否有任何目的?我错过了什么吗?
答案 0 :(得分:56)
typedef <type> <alias>
和<type> typedef <alias>
都有效的事实只来自语言语法定义。
typedef
被归类为存储类规范器(就像static
,auto
),类型本身被称为类型说明符。根据标准第6.7节中的语法定义,您将看到它们可以互换:
declaration:
declaration-specifiers init-declarator-list ;
declaration-specifiers:
storage-class-specifier declaration-specifiers
type-specifier declaration-specifiers
type-qualifier declaration-specifiers
function-specifier declaration-specifiers
init-declarator-list:
init-declarator
init-declarator-list , init-declarator
init-declarator:
declarator
declarator = initializer
(当然,请注意,结构和非结构同样如此,这意味着double typedef trouble;
也是有效的。)
答案 1 :(得分:18)
正如其他人所说,typedef
是存储类说明符,与其他存储类说明符一样,您也可以在类型和声明符之间放置说明符。
虽然这是有效的,但它也是一种应该避免的形式,因为C将其标记为过时功能:
(C11,6.11.5p1)&#34;声明中声明说明符开头以外的存储类说明符的位置是一个过时的功能。&#34;
答案 2 :(得分:6)
两者具有相同的含义。这两种形式都有效:
typedef <existing_type> <new_type>
<existing_type> typedef <new_type>
您可以通过以下两种方式typedef
上述结构:
struct X {
USHORT x;
}typedef X, *PX; // <existing_type> typedef <new_type>
或
typedef struct {
USHORT x;
} X, *PX; // typedef <existing_type> <new_type>
答案 3 :(得分:5)
您真的可以按照您想要的任何顺序放置所有声明说明符!任何*
指针和实际声明符(变量或新类型名称)的位置都很重要,但所有typedef
int
unsigned
const
{{1等等东西可以是任何顺序。
如果你看一下C的官方语法,它只是说:
static
declaration:
declaration-specifiers init-declarator-list ;
是所有存储类说明符(declaration-specifiers
,typedef
等),类型说明符(实际类型,如extern
或{{1} }),键入限定符(int
和struct X
),以及其他一些不常见的限定符。他们的命令并不重要。第二部分是const
,它是变量或新类型名称(在typedef的情况下),任何volatile
个字符,变量的初始化(init-declarator-list
),以及更多。声明器部分中的事物顺序很重要,但不是声明说明符中的顺序。
答案 4 :(得分:5)
免责声明:这不是一个技术问题,而是一个实际的答案。有关技术问题,请参阅其他答案。这个答案读起来是固执的和主观的,但请在我试图解释更大的图片时请耐心等待。
struct
是一个奇怪的野兽,因为你放在右括号}
和分号;
之间的东西是指那些括号内或之前的内容。我知道为什么会这样,而且从语法角度来说它确实有意义,但我个人觉得这很反直觉,因为花括号通常意味着范围:
反直觉的例子:
// declares a variable named `foo` of unnamed struct type.
struct {
int x, y;
} foo;
foo.x = 1;
// declares a type named `Foo` of unnamed struct type
struct {
int x, y;
} typedef Foo;
Foo foo2;
foo2.x = 2;
// declares a type named `Baz` of the struct named `Bar`
struct Bar {
int x, y;
} typedef Baz;
// note the 'struct' keyword to actually use the type 'Bar'
struct Bar bar;
bar.x = 3;
Baz baz;
baz.x = 4;
如果像这样使用struct
和typedef
s的密集语法,那么有许多微妙的事情可能会出错。如下所示,很容易意外地声明变量而不是类型。编译器只有有限的帮助,因为几乎所有组合在语法上都是正确的。它们并不一定意味着您尝试表达的内容。这是pit of despair。
错误的例子:
// mixed up variable and type declaration
struct foo {
int x, y;
} Foo;
// declares a type 'foo' instead of a variable
typedef struct Foo {
int x, y;
} foo;
// useless typedef but compiles fine
typedef struct Foo {
int x, y;
};
// compiler error
typedef Foo struct {
int x, y;
};
出于可读性和维护的原因,我更喜欢单独声明所有内容,并且从不将任何内容放在最后的花括号中。直观的语法很容易超过额外代码行的成本。我认为这种方法makes it easy to do the right things and annoying to do the wrong things。
直观的例子:
// declares a struct named 'TVector2'
struct TVector2 {
float x, y;
};
// declares a type named 'Vector2' to get rid of the 'struct' keyword
// note that I really never use 'TVector2' afterwards
typedef struct TVector2 Vector2;
Vector2 v, w;
v.x = 0;
v.y = 1;