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

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

elem user;

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


当前回答

使用typedef可以避免每次声明该类型的变量时都要写struct:

struct elem
{
 int i;
 char k;
};
elem user; // compile error!
struct elem user; // this is correct

其他回答

在C99中,typedef是必需的。它已经过时了,但是很多工具(比如HackRank)使用c99作为它的纯C实现。这里需要typedef。

我不是说他们应该改变(也许有两个C选项),如果要求改变,我们这些在网站上学习面试的人将是SOL。

让我们从最基本的开始,慢慢来。

下面是一个结构定义的例子:

struct point
  {
    int x, y;
  };

这里的名称点是可选的。

结构可以在定义期间声明,也可以在定义之后声明。

在定义期间声明

struct point
  {
    int x, y;
  } first_point, second_point;

在定义之后声明

struct point
  {
    int x, y;
  };
struct point first_point, second_point;

现在,仔细注意上面的最后一种情况;如果您决定稍后在代码中创建该类型,则需要编写struct point来声明该类型的结构。

输入类型。如果您打算在稍后使用相同的蓝图在程序中创建新的Structure (Structure是自定义数据类型),那么在定义过程中使用typedef可能是一个好主意,因为您可以节省一些输入。

typedef struct point
  {
    int x, y;
  } Points;

Points first_point, second_point;

在命名自定义类型时要注意一点

没有什么可以阻止您在自定义类型名称的末尾使用_t后缀,但POSIX标准保留使用后缀_t来表示标准库类型名称。

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;

这到底有什么意义?

在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++类。

令人惊讶的是,很多人都错了。请不要在C中定义结构类型,它不必要地污染全局命名空间,在大型C程序中,全局命名空间通常已经被严重污染。

此外,没有标记名的类型定义结构是头文件之间不必要的排序关系的主要原因。

考虑:

#ifndef FOO_H
#define FOO_H 1

#define FOO_DEF (0xDEADBABE)

struct bar; /* forward declaration, defined in bar.h*/

struct foo {
  struct bar *bar;
};

#endif

使用这样的定义,不使用typedef,编译单元可以包含foo.h来获得FOO_DEF定义。如果它不试图解引用foo结构体的'bar'成员,那么就不需要包含"bar.h"文件。

此外,由于标签名和成员名之间的名称空间是不同的,因此可以编写非常可读的代码,例如:

struct foo *foo;

printf("foo->bar = %p", foo->bar);

由于名称空间是分开的,因此在命名变量时与其struct标记名一致时不存在冲突。

如果我必须维护你的代码,我会删除你的类型定义结构。