Stackoverflow热门问题(五)-typedef struct 与 struct 定义的不同

stackoverflow热门问题目录

typedef struct 与 struct 定义的不同

  • user69514 asked:
    • 作为C语言编程的初学者,我很好奇当我定义一个结构体的时候,用不用typedef有什么区别?我感觉似乎没差,它们都完成了同样的事情。
    • struct myStruct{
    • int one;
    • int two;
    • };
    • vs.
    • typedef struct{
    • int one;
    • int two;
    • }myStruct;
  • 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位用户认为有用
      • structtypedef区别很大。
      • struct关键字被用来定义或参考一个结构体类型,例如:
      • struct foo {
      • int n;
      • };
      • 上面这段代码可以定义一个新类型struct foofoo是标签,只有跟在struct关键字后才有意义,因为标签或其它标识符保存于不同的命名空间(这与C++的命名空间很像,但限制更多)。
      • 至于typedef,它并不定义新类型,它只是单纯给已存在的类型添加了别名而已,例如:
      • typedef int my_int;
      • my_int是一个int的新名称,my_intint是相同的类型。类似的,可以对struct定义个别名,例如:
      • typedef struct foo foo;
      • struct foo是已存在的类型名,typedef为其添加了别名foo
      • C语言的语法允许你在单个声明里面混合使用structtypedef
      • 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名,如果需要的话,还能同时使用完整的结构体名。

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 using typedef. It seems to me like there’s really no difference, they accomplish the same goal.
      • 作为C语言编程的初学者,我很好奇当我定义一个结构体的时候,用不用typedef有什么区别?我感觉似乎没差,它们都完成了同样的事情。
    • struct myStruct{
    • int one;
    • int two;
    • };
    • vs.
    • typedef struct{
    • int one;
    • int two;
    • }myStruct;
  • 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 as struct 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++
      • 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 for S 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 struct S 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 the struct keyword:
        • 在上面第二行定义函数S后,struct S就不能自动被编译器解析,因此在使用这个类型创建对象或者定义参数时,必须在前面加上struct关键字:
      • // previous code here...(接上个代码块)
      • int main() {
      • S();
      • struct S s;
      • }
    • Keith Thompson – 154位用户认为有用
      • struct and typedef are two very different things.
        • structtypedef区别很大。
      • 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 name foo is a tag; it’s meaningful only when it’s immediately preceded by the struct keyword, because tags and other identifiers are in distinct name spaces. (This is similar to, but much more restricted than, the C++ concept of namespaces.)
        • 上面这段代码可以定义一个新类型struct foofoo是标签,只有跟在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 for int; my_int and int are exactly the same type. Similarly, given the struct definition above, you can write:
        • my_int是一个int的新名称,my_intint是相同的类型。类似的,可以对struct定义个别名,例如:
      • typedef struct foo foo;
      • The type already has a name, struct foo. The typedef declaration gives the same type a new name, foo.
        • struct foo是已存在的类型名,typedef为其添加了别名foo
      • The syntax allows you to combine a struct and typedef into a single declaration:
        • C语言的语法允许你在单个声明里面混合使用structtypedef
      • 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 as bar.
        • 上面是普遍写法。这样可以用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 as struct bar. The typedef 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 member n 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 just blah, 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名,如果需要的话,还能同时使用完整的结构体名。

You may also like...

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注