最近我正在阅读nginx源代码。有如此多的结构定义为
typedef struct {
field_1;
field_2;
/* ... */
} some_obj_t;
但仍有一些其他结构被定义为
struct some_obj_s {
field_1;
field_2;
/* ... */
};
然后,在其他头文件中,例如ngx_core.h
,执行一些typedef
:
typedef struct some_obj_s some_obj_t;
我的问题是(可能重复......):
typedef
定义上使用struct
?是否有任何OO或设计模式考虑因素? 答案 0 :(得分:3)
在结构上使用typedef主要是为了方便起见。例如:
typedef struct List_
{
...
} List;
这允许您将List类型的变量简单地定义为:
List myList;
而不是:
struct List_ myList;
所有这些额外的struct语句都会使代码混乱。在你展示它时使用typedef的另一种方法是将一种类型实现为另一种类型。例如:
typedef List Queue;
这将新类型Queue定义为先前定义的类型List。然后,这允许您像使用List一样使用Queue。
答案 1 :(得分:1)
不同的用途反映了是否在接口中使用了类型(仅限),或者是否必须知道结构信息。
符号:
typedef struct some_obj_s some_obj_t;
告诉编译器,结构类型包含标记some_obj_s
和typedef name some_obj_t
。如果此类型是用户的opaque类型,则无需指定结构的详细信息。采用some_obj_t *
参数(可能是合格的)或返回此类值的函数可以在没有进一步信息的情况下声明和使用。 (你甚至可以声明这种类型的extern
variables,因为编译器主要需要一个地址。)类型不完整(也称为不透明),但可以完成。
在实现的某个地方,您会找到结构类型的定义(除了在最不寻常的情况下),例如:
struct some_obj_s
{
...members defined...
};
如果此声明(定义)在范围内,您可以创建类型为some_obj_t
或struct some_obj_s
的变量,以及指向该类型的指针。代码可以使用结构的成员。
符号:
typedef struct /* no tag */
{
...
} another_obj_t;
定义无标记结构类型。提供了类型的详细信息,因此类型已完成。
您可能还会看到:
typedef struct yao_s
{
...members defined...
} yao_t;
这两者都声明了结构类型及其标签和typedef。
单独的typedef具有自引用结构的优势,例如列表:
typedef struct GenericList GenericList;
struct GenericList
{
void *data;
GenericList *next;
GenericList *prev;
};
如果没有单独的typedef
行,则必须在结构中编写struct GenericList
。这意味着同样的事情;你仍然可以写它;但是使用单独的typedef,您可以在结构中使用相同的表示法,稍后将引用它。
请注意,POSIX reserves类型名称以_t
结尾,用于实现。这意味着在您自己的代码中使用该约定会很危险。
不需要为tag和typedef使用单独的名称(如GenericList
示例所示),尽管_s
和_t
后缀也是一个众所周知的约定。 C ++自动将标记转换为类型名称而不需要显式的typedef(但允许使用显式的typedef),因此我通常对标记和类型使用相同的名称。
答案 2 :(得分:0)
为什么作者不使用相同的形式来定义所有结构?
因为他们采用了某种编码风格。
例如,Linux内核编码标准使用没有typedef的结构表示法。这是纯粹的编码风格,他们没有令人信服的理由为什么他们这样做,他们只是相信代码中的'struct'提高了可读性,因为他们认为typedef“隐藏了类型”。
其他人不同意,例如Windows API全部使用typedef表示法,而不是结构表。我想说这种编码风格更为常见,因为它提醒了很多支持OO的语言风格:C ++,Java,C#等。
任何形式都不能轻易被证明是正确的,这一切都非常主观。像大多数编码风格一样重要。
确实有。 C中有一些称为opaque或incomplete类型的东西,它允许你实现变量的真正私有封装。 See this example我昨天发布了。在哪种情况下我们应该在结构定义上使用typedef?是否有任何OO或设计模式考虑因素?
在该示例中,头文件中有typedef struct vector vector;
,它基本上创建了一个抽象基类:调用者可以创建指针但不能分配的对象。调用者永远无法访问struct成员。
然后在.c文件中,结构的实现为struct vector { ... };
,只对.c文件可见,而不是对调用者可见。
答案 3 :(得分:-1)
请按照以下链接找到第二个问题的答案: