Stackoverflow热门问题(五)-typedef struct 与 struct 定义的不同
typedef struct 与 struct 定义的不同
- user69514 asked:
- 作为C语言编程的初学者,我很好奇当我定义一个结构体的时候,用不用
typedef
有什么区别?我感觉似乎没差,它们都完成了同样的事情。 struct myStruct{
int one;
int two;
};
- vs.
typedef struct{
int one;
int two;
}myStruct;
- 作为C语言编程的初学者,我很好奇当我定义一个结构体的时候,用不用
- Answers:
- David Rodríguez - dribeas - 1131位用户认为有用
- 常见用法是同时使用两者:
typedef struct S {
int x;
} S;
- 它们是不同的定义方式。为了让后续讨论更易理解,我将它分成以下两行:
- 注:这里的行是以分号;结尾,而不是以换行符结尾,即一行为一完整代码端。
struct S {
int x;
};
typedef struct S S;
- 第一行的作用,是在结构体命名空间(struct name space)中定义一个标识符S(C++不是这么做的)。即定义一个新的参数类型struct S,并可将之用来定义变量或者函数参数,像这样:
void f( struct S argument ); // struct is required here
(需要struct)- 第二行形式,则是在全局命名空间,为
struct S
类型添加一个新的别名S
,像这样: void f( S argument ); // struct keyword no longer needed
(不需要struct)- 需要注意的一点是标识符命名空间的不同,会导致在结构体命名空间定义
S
后,再在全局命名空间定义S
,并不会报错,这正是因为这个操作并不是重新定义这个标识符,只是在另一个空间创建了另一个标识符而已。 - 为了理解这点,可以看下面的例子:
typedef struct S {
int x;
} T;
void S() { } // correct
//void T() {} // error: symbol T already defined as an alias to 'struct S'
- 即,因为标识符保存空间的不同,你可以定义一个函数,它的函数名与某一结构体标识符名一致。但不能与使用了
typedef
的标识符的名称一致。 - C++略有不同,它定位标识符的规则有点变化。C++同样有两个不同标识符空间,但与C不同的是,如果你只定义了一个
struct/class
标识符,而没有定义其同名函数,那么不需要加struct/class
。 // C++
struct S {
int x;
}; // S defined as a class
(S定义为类)void f( S a ); // correct: struct is optional
(struct可选)- 实际上,这只是搜索规则的改变,而不是说标识符定义在了其它位置。编译器将会首先在全局标识符表中搜索,如果没有搜索到
S
,那么将在类标识符中搜索。 - 之前展示过的代码在C++中效果一样:
typedef struct S {
int x;
} T;
void S() {} // correct [*]
//void T() {} // error: symbol T already defined as an alias to 'struct S'
- 在上面第二行定义函数
S
后,struct S
就不能自动被编译器解析,因此在使用这个类型创建对象或者定义参数时,必须在前面加上struct
关键字: // previous code here...
(接上个代码块)int main() {
S();
struct S s;
}
- Keith Thompson - 154位用户认为有用
struct
与typedef
区别很大。struct
关键字被用来定义或参考一个结构体类型,例如:struct foo {
int n;
};
- 上面这段代码可以定义一个新类型
struct foo
。foo
是标签,只有跟在struct
关键字后才有意义,因为标签或其它标识符保存于不同的命名空间(这与C++的命名空间很像,但限制更多)。 - 至于
typedef
,它并不定义新类型,它只是单纯给已存在的类型添加了别名而已,例如: typedef int my_int;
my_int
是一个int
的新名称,my_int
与int
是相同的类型。类似的,可以对struct
定义个别名,例如:typedef struct foo foo;
struct foo
是已存在的类型名,typedef
为其添加了别名foo
。- C语言的语法允许你在单个声明里面混合使用
struct
与typedef
: typedef struct bar {
int n;
} bar;
- 上面是普遍写法。这样可以用
struct bar
或者bar
来表示这个结构体类型。 - 值得注意的是,
typedef
定义的别名在其出现前并不可用,这体现在当在结构体中包含指向自己的指针时,一定得需要struct
关键字。 typedef struct node {
int data;
struct node *next; /* can't use just "node *next" here */
} node;
- 有的程序员会使用不同的标识符来表示标签与typedef名。在我看来,这完全没必要,因为使用相同的名称是完全合法的,还能提高可读性。不过如果你坚持要使用不同标识符,至少使用同一种命名方式:
typedef struct node_s {
/* ... */
} node;
- (就我个人认为,我更喜欢省略typedef对struct bar的参考。因为typedef在简写的同时,还隐藏了它是个结构体的事实。如果你不希望让类型透明,这种做法很不错。即,如果代码想要用成员n的名称来引用它,它并不是不是透明的,那么很明显能知道它是结构体。但也有很多人不同意这个观点,所以最好对两种写法都有了解。)
- (C++的语法则略有不同。例如声明struct blah,可以在不使用typedef的情况下使用blah来引用它。因此,使用typedef会使得你的C代码更像C++,如果你觉得这样不错的话。)
- R Samuel Klatchko - 92位用户认为有用
- 另一个没有被指出的不同,是给结构体一个名称后,可以提供结构体的前向声明。所以在一些其它文件中,可以这么写:
- 译者注:这句话我完全没看懂。
struct myStruct;
void doit(struct myStruct *ptr);
- 而不需要访问该定义。我推荐提问者将两个例子混合起来用,像这样:
typedef struct myStruct{
int one;
int two;
} myStruct;
- 它允许你使用更简洁的typedef名,如果需要的话,还能同时使用完整的结构体名。
- 另一个没有被指出的不同,是给结构体一个名称后,可以提供结构体的前向声明。所以在一些其它文件中,可以这么写:
- David Rodríguez - dribeas - 1131位用户认为有用
typedef struct vs struct definitions
- user69514 asked:
- I'm a beginner in C programming, but I was wondering what's the difference between using
typedef
when defining a structure versus not usingtypedef
. It seems to me like there's really no difference, they accomplish the same goal.- 作为C语言编程的初学者,我很好奇当我定义一个结构体的时候,用不用
typedef
有什么区别?我感觉似乎没差,它们都完成了同样的事情。
- 作为C语言编程的初学者,我很好奇当我定义一个结构体的时候,用不用
struct myStruct{
int one;
int two;
};
- vs.
typedef struct{
int one;
int two;
}myStruct;
- I'm a beginner in C programming, but I was wondering what's the difference between using
- Answers:
- David Rodríguez - dribeas - 1131位用户认为有用
- The common idiom is using both:
- 常见用法是同时使用两者:
typedef struct S {
int x;
} S;
- They are different definitions. To make the discussion clearer I will split the sentence:
- 它们是不同的定义方式。为了让后续讨论更易理解,我将它分成以下两行:
- 注:这里的行是以分号;结尾,而不是以换行符结尾,即一行为一完整代码端。
- 它们是不同的定义方式。为了让后续讨论更易理解,我将它分成以下两行:
struct S {
int x;
};
typedef struct S S;
- In the first line you are defining the identifier
S
within the struct name space (not in the C++ sense). You can use it and define variables or function arguments of the newly defined type by defining the type of the argument asstruct S
:- 第一行的作用,是在结构体命名空间(struct name space)中定义一个标识符S(C++不是这么做的)。即定义一个新的参数类型struct S,并可将之用来定义变量或者函数参数,像这样:
void f( struct S argument ); // struct is required here
(需要struct)- The second line adds a type alias
S
in the global name space and thus allows you to just write:- 第二行形式,则是在全局命名空间,为
struct S
类型添加一个新的别名S
,像这样:
- 第二行形式,则是在全局命名空间,为
void f( S argument ); // struct keyword no longer needed
(不需要struct)- Note that since both identifier name spaces are different, defining
S
both in the structs and global spaces is not an error, as it is not redefining the same identifier, but rather creating a different identifier in a different place.- 需要注意的一点是标识符命名空间的不同,会导致在结构体命名空间定义
S
后,再在全局命名空间定义S
,并不会报错,这正是因为这个操作并不是重新定义这个标识符,只是在另一个空间创建了另一个标识符而已。
- 需要注意的一点是标识符命名空间的不同,会导致在结构体命名空间定义
- To make the difference clearer:
- 为了理解这点,可以看下面的例子:
typedef struct S {
int x;
} T;
void S() { } // correct
//void T() {} // error: symbol T already defined as an alias to 'struct S'
- You can define a function with the same name of the struct as the identifiers are kept in different spaces, but you cannot define a function with the same name as a
typedef
as those identifiers collide.- 即,因为标识符保存空间的不同,你可以定义一个函数,它的函数名与某一结构体标识符名一致。但不能与使用了
typedef
的标识符的名称一致。
- 即,因为标识符保存空间的不同,你可以定义一个函数,它的函数名与某一结构体标识符名一致。但不能与使用了
- In C++, it is slightly different as the rules to locate a symbol have changed subtly. C++ still keeps the two different identifier spaces, but unlike in C, when you only define the symbol within the class identifier space, you are not required to provide the struct/class keyword:
- C++略有不同,它定位标识符的规则有点变化。C++同样有两个不同标识符空间,但与C不同的是,如果你只定义了一个
struct/class
标识符,而没有定义其同名函数,那么不需要加struct/class
。
- C++略有不同,它定位标识符的规则有点变化。C++同样有两个不同标识符空间,但与C不同的是,如果你只定义了一个
// C++
struct S {
int x;
}; // S defined as a class
(S定义为类)void f( S a ); // correct: struct is optional
(struct可选)- What changes are the search rules, not where the identifiers are defined. The compiler will search the global identifier table and after
S
has not been found it will search forS
within the class identifiers.- 实际上,这只是搜索规则的改变,而不是说标识符定义在了其它位置。编译器将会首先在全局标识符表中搜索,如果没有搜索到
S
,那么将在类标识符中搜索。
- 实际上,这只是搜索规则的改变,而不是说标识符定义在了其它位置。编译器将会首先在全局标识符表中搜索,如果没有搜索到
- The code presented before behaves in the same way:
- 之前展示过的代码在C++中效果一样:
typedef struct S {
int x;
} T;
void S() {} // correct [*]
//void T() {} // error: symbol T already defined as an alias to 'struct S'
- After the definition of the
S
function in the second line, the structS
cannot be resolved automatically by the compiler, and to create an object or define an argument of that type you must fall back to including thestruct
keyword:- 在上面第二行定义函数
S
后,struct S
就不能自动被编译器解析,因此在使用这个类型创建对象或者定义参数时,必须在前面加上struct
关键字:
- 在上面第二行定义函数
// previous code here...
(接上个代码块)int main() {
S();
struct S s;
}
- The common idiom is using both:
- Keith Thompson - 154位用户认为有用
struct
andtypedef
are two very different things.struct
与typedef
区别很大。
- The
struct
keyword is used to define, or to refer to, a structure type. For example, this:struct
关键字被用来定义或参考一个结构体类型,例如:
struct foo {
int n;
};
- creates a new type called
struct foo
. The namefoo
is a tag; it's meaningful only when it's immediately preceded by thestruct
keyword, because tags and other identifiers are in distinct name spaces. (This is similar to, but much more restricted than, the C++ concept ofnamespace
s.)- 上面这段代码可以定义一个新类型
struct foo
。foo
是标签,只有跟在struct
关键字后才有意义,因为标签或其它标识符保存于不同的命名空间(这与C++的命名空间很像,但限制更多)。
- 上面这段代码可以定义一个新类型
- A
typedef
, in spite of the name, does not define a new type; it merely creates a new name for an existing type. For example, given:- 至于
typedef
,它并不定义新类型,它只是单纯给已存在的类型添加了别名而已,例如:
- 至于
typedef int my_int;
my_int
is a new name forint
;my_int
andint
are exactly the same type. Similarly, given thestruct
definition above, you can write:my_int
是一个int
的新名称,my_int
与int
是相同的类型。类似的,可以对struct
定义个别名,例如:
typedef struct foo foo;
- The type already has a name,
struct foo
. Thetypedef
declaration gives the same type a new name,foo
.struct foo
是已存在的类型名,typedef
为其添加了别名foo
。
- The syntax allows you to combine a
struct
andtypedef
into a single declaration:- C语言的语法允许你在单个声明里面混合使用
struct
与typedef
:
- C语言的语法允许你在单个声明里面混合使用
typedef struct bar {
int n;
} bar;
- This is a common idiom. Now you can refer to this structure type either as
struct bar
or just asbar
.- 上面是普遍写法。这样可以用
struct bar
或者bar
来表示这个结构体类型。
- 上面是普遍写法。这样可以用
- Note that the typedef name doesn't become visible until the end of the declaration. If the structure contains a pointer to itself, you have use the
struct
version to refer to it:- 值得注意的是,
typedef
定义的别名在其出现前并不可用,这体现在当在结构体中包含指向自己的指针时,一定得需要struct
关键字。
- 值得注意的是,
typedef struct node {
int data;
struct node *next; /* can't use just "node *next" here */
} node;
- Some programmers will use distinct identifiers for the struct tag and for the typedef name. In my opinion, there's no good reason for that; using the same name is perfectly legal and makes it clearer that they're the same type. If you must use different identifiers, at least use a consistent convention:
- 有的程序员会使用不同的标识符来表示标签与typedef名。在我看来,这完全没必要,因为使用相同的名称是完全合法的,还能提高可读性。不过如果你坚持要使用不同标识符,至少使用同一种命名方式:
typedef struct node_s {
/* ... */
} node;
- (Personally, I prefer to omit the
typedef
and refer to the type asstruct bar
. Thetypedef
save a little typing, but it hides the fact that it's a structure type. If you want the type to be opaque, this can be a good thing. If client code is going to be referring to the membern
by name, then it's not opaque; it's visibly a structure, and in my opinion it makes sense to refer to it as a structure. But plenty of smart programmers disagree with me on this point. Be prepared to read and understand code written either way.)- (就我个人认为,我更喜欢省略typedef对struct bar的参考。因为typedef在简写的同时,还隐藏了它是个结构体的事实。如果你不希望让类型透明,这种做法很不错。即,如果代码想要用成员n的名称来引用它,它并不是不是透明的,那么很明显能知道它是结构体。但也有很多人不同意这个观点,所以最好对两种写法都有了解。)
- (C++ has different rules. Given a declaration of
struct blah
, you can refer to the type as justblah
, even without a typedef. Using a typedef might make your C code a little more C++-like -- if you think that's a good thing.)- (C++的语法则略有不同。例如声明struct blah,可以在不使用typedef的情况下使用blah来引用它。因此,使用typedef会使得你的C代码更像C++,如果你觉得这样不错的话。)
- R Samuel Klatchko - 92位用户认为有用
- Another difference not pointed out is that giving the struct a name (i.e. struct myStruct) also enables you to provide forward declarations of the struct. So in some other file, you could write:
- 另一个没有被指出的不同,是给结构体一个名称后,可以提供结构体的前向声明。所以在一些其它文件中,可以这么写:
- 译者注:这句话我完全没看懂。
- 另一个没有被指出的不同,是给结构体一个名称后,可以提供结构体的前向声明。所以在一些其它文件中,可以这么写:
struct myStruct;
void doit(struct myStruct *ptr);
- without having to have access to the definition. What I recommend is you combine your two examples:
- 而不需要访问该定义。我推荐提问者将两个例子混合起来用,像这样:
typedef struct myStruct{
int one;
int two;
} myStruct;
- This gives you the convenience of the more concise typedef name but still allows you to use the full struct name if you need.
- 它允许你使用更简洁的typedef名,如果需要的话,还能同时使用完整的结构体名。
- Another difference not pointed out is that giving the struct a name (i.e. struct myStruct) also enables you to provide forward declarations of the struct. So in some other file, you could write:
- David Rodríguez - dribeas - 1131位用户认为有用
共有 0 条评论