我见过许多由如下结构组成的程序

typedef struct 
{
    int i;
    char k;
} elem;

elem user;

为什么如此频繁地需要它?有什么具体原因或适用领域吗?


当前回答

一个> typdef允许为数据类型创建更有意义的同义词,从而帮助定义程序的含义和文档化。此外,它们还有助于参数化程序以解决可移植性问题(K&R, pg147, C prog lang)。

B > 结构定义了一种类型。Structs允许方便地将变量集合分组,以便将(K&R, pg127, C prog lang.)作为单个单元处理

C > 结构的类型定义在上面的a中有解释。

对我来说,struct是自定义类型、容器、集合、命名空间或复杂类型,而typdef只是一种创建更多昵称的方法。

其他回答

摘自Dan Saks的一篇旧文章(http://www.ddj.com/cpp/184403396?pgno=3):)


The C language rules for naming structs are a little eccentric, but they're pretty harmless. However, when extended to classes in C++, those same rules open little cracks for bugs to crawl through. In C, the name s appearing in struct s { ... }; is a tag. A tag name is not a type name. Given the definition above, declarations such as s x; /* error in C */ s *p; /* error in C */ are errors in C. You must write them as struct s x; /* OK */ struct s *p; /* OK */ The names of unions and enumerations are also tags rather than types. In C, tags are distinct from all other names (for functions, types, variables, and enumeration constants). C compilers maintain tags in a symbol table that's conceptually if not physically separate from the table that holds all other names. Thus, it is possible for a C program to have both a tag and an another name with the same spelling in the same scope. For example, struct s s; is a valid declaration which declares variable s of type struct s. It may not be good practice, but C compilers must accept it. I have never seen a rationale for why C was designed this way. I have always thought it was a mistake, but there it is. Many programmers (including yours truly) prefer to think of struct names as type names, so they define an alias for the tag using a typedef. For example, defining struct s { ... }; typedef struct s S; lets you use S in place of struct s, as in S x; S *p; A program cannot use S as the name of both a type and a variable (or function or enumeration constant): S S; // error This is good. The tag name in a struct, union, or enum definition is optional. Many programmers fold the struct definition into the typedef and dispense with the tag altogether, as in: typedef struct { ... } S;


这篇链接的文章还讨论了不需要类型定义的c++行为是如何导致微妙的名称隐藏问题的。为了防止这些问题,在c++中对类和结构进行类型定义也是一个好主意,尽管乍一看似乎没有必要。在c++中,有了类型定义,隐藏的名称就变成了编译器告诉你的错误,而不是潜在问题的隐藏来源。

Typedef不会提供一组相互依赖的数据结构。你不能用typdef做到这一点:

struct bar;
struct foo;

struct foo {
    struct bar *b;
};

struct bar {
    struct foo *f;
};

当然你还可以加上:

typedef struct foo foo_t;
typedef struct bar bar_t;

这到底有什么意义?

Linux内核编码风格第5章给出了使用typedef的优点和缺点(主要是缺点)。

Please don't use things like "vps_t". It's a mistake to use typedef for structures and pointers. When you see a vps_t a; in the source, what does it mean? In contrast, if it says struct virtual_container *a; you can actually tell what "a" is. Lots of people think that typedefs "help readability". Not so. They are useful only for: (a) totally opaque objects (where the typedef is actively used to hide what the object is). Example: "pte_t" etc. opaque objects that you can only access using the proper accessor functions. NOTE! Opaqueness and "accessor functions" are not good in themselves. The reason we have them for things like pte_t etc. is that there really is absolutely zero portably accessible information there. (b) Clear integer types, where the abstraction helps avoid confusion whether it is "int" or "long". u8/u16/u32 are perfectly fine typedefs, although they fit into category (d) better than here. NOTE! Again - there needs to be a reason for this. If something is "unsigned long", then there's no reason to do typedef unsigned long myflags_t; but if there is a clear reason for why it under certain circumstances might be an "unsigned int" and under other configurations might be "unsigned long", then by all means go ahead and use a typedef. (c) when you use sparse to literally create a new type for type-checking. (d) New types which are identical to standard C99 types, in certain exceptional circumstances. Although it would only take a short amount of time for the eyes and brain to become accustomed to the standard types like 'uint32_t', some people object to their use anyway. Therefore, the Linux-specific 'u8/u16/u32/u64' types and their signed equivalents which are identical to standard types are permitted -- although they are not mandatory in new code of your own. When editing existing code which already uses one or the other set of types, you should conform to the existing choices in that code. (e) Types safe for use in userspace. In certain structures which are visible to userspace, we cannot require C99 types and cannot use the 'u32' form above. Thus, we use __u32 and similar types in all structures which are shared with userspace. Maybe there are other cases too, but the rule should basically be to NEVER EVER use a typedef unless you can clearly match one of those rules. In general, a pointer, or a struct that has elements that can reasonably be directly accessed should never be a typedef.

您(可选地)给结构的名称称为标记名称,正如前面所指出的,它本身并不是一个类型。要获得该类型,需要使用结构体前缀。

除了GTK+,我不确定tagname是否像struct类型的typedef一样常用,所以在c++中,这是可以识别的,你可以省略struct关键字,并使用tagname作为类型名:

struct MyStruct
{
  int i;
};

// The following is legal in C++:
MyStruct obj;
obj.i = 7;

在C语言中,struct/union/enum是由C语言预处理器处理的宏指令(不要与处理“#include”和other的预处理器混淆)

so :

struct a
{
   int i;
};

struct b
{
   struct a;
   int i;
   int j;
};

结构b是这样展开的:

struct b
{
    struct a
    {
        int i;
    };
    int i;
    int j;
}

因此,在编译时,它在堆栈上的演变是这样的: b: int人工智能 int我 int j

这也是为什么在不能终止的déclaration循环中很难有自不同的结构,C预处理器循环。

typedef是类型说明符,这意味着只有C编译器处理它,它可以像他想要的那样优化汇编代码实现。它也不会像préprocessor那样愚蠢地使用par类型的成员,而是使用更复杂的引用构造算法,因此构造如下:

typedef struct a A; //anticipated declaration for member declaration

typedef struct a //Implemented declaration
{
    A* b; // member declaration
}A;

是允许的,功能齐全。当执行线程离开初始化函数的应用程序字段时,这个实现还允许访问编译器类型转换,并删除一些bug影响。

这意味着在C中,typedef比单独的结构体更接近c++类。