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

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

elem user;

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


当前回答

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

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

其他回答

我认为typedef甚至不可能实现前向声明。使用struct, enum和union允许在依赖关系(知道)是双向的情况下转发声明。

风格: 在c++中使用typedef是很有意义的。在处理需要多个和/或变量参数的模板时,它几乎是必要的。typedef有助于保持命名的直直性。

在C编程语言中并非如此。typedef的使用通常没有任何目的,只会混淆数据结构的使用。由于只有{struct (6), enum (4), union(5)}个按键被用于声明一个数据类型,因此结构的别名几乎没有任何用处。数据类型是联合还是结构?使用简单的非类型定义声明可以让您立即知道它是什么类型。

请注意Linux是如何在编写时严格避免typedef带来的这种无意义的别名的。结果是一个极简主义和干净的风格。

一个有用的信息来源是《Expert C Programming》(第3章)。简单地说,在C语言中你有多个命名空间:标记、类型、成员名和标识符。Typedef为类型引入别名,并将其定位在标记命名空间中。也就是说,

typedef struct Tag{
...members...
}Type;

定义了两个东西。1)在标签命名空间中标记,2)在类型命名空间中键入。你可以同时使用myType和struct Tag myTagType。像struct Type myType或Tag myTagType这样的声明是非法的。此外,在这样的声明中:

typedef Type *Type_ptr;

定义一个指向类型的指针。如果我们声明:

Type_ptr var1, var2;
struct Tag *myTagType1, myTagType2;

那么var1,var2和myTagType1是指向Type的指针,而myTagType2不是。

在上面提到的书中,它提到对结构进行类型定义并不是很有用,因为它只是让程序员不用编写struct这个词。然而,像许多其他C程序员一样,我有一个反对意见。虽然有时会混淆一些名称(这就是为什么在像内核这样的大型代码库中不可取的原因),但当您想在C中实现多态性时,查看这里的详细信息会有很大帮助。例子:

typedef struct MyWriter_t{
    MyPipe super;
    MyQueue relative;
    uint32_t flags;
...
}MyWriter;

你可以:

void my_writer_func(MyPipe *s)
{
    MyWriter *self = (MyWriter *) s;
    uint32_t myFlags = self->flags;
...
}

因此,您可以通过强制转换通过内部结构(mpipe)访问外部成员(flags)。对我来说,强制转换整个类型比执行(struct MyWriter_ *) s;每次你想执行这样的功能。在这种情况下,简要引用是很重要的,特别是当你在代码中大量使用这种技术时。

最后,与宏相比,类型定义类型的最后一个方面是无法扩展它们。例如,你有:

#define X char[10] or
typedef char Y[10]

然后你可以声明

unsigned X x; but not
unsigned Y y;

对于结构体,我们并不关心这一点,因为它不适用于存储说明符(volatile和const)。

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

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

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;

这到底有什么意义?

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

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

struct MyStruct
{
  int i;
};

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