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.
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.
//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.
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:
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.
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:
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.)
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语言的语法允许你在单个声明里面混合使用struct与typedef:
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:
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:
(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.)
(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.)
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:
近期评论