在C中使用typedef时,是否使用指向struct的指针

时间:2011-02-23 23:58:49

标签: c list pointers struct typedef

为了在C中定义新的数据类型,例如链表的类型,可以使用以下定义之一

struct list_node {
    int x;
    struct list_node * next;
};

//1
typedef struct list_node list1;
//2
typedef struct list_node *list2;

从我所看到的,通常的做法是第一个定义。

问题是第二个定义是否也是可以接受的做法。 在哪种情况下,如果有人应该比第一个更喜欢第二个? 前提是我们使用的变量是struct list_node的指针 是否可以对两种类型进行相同的操作? 第一个有什么好处?

5 个答案:

答案 0 :(得分:5)

我要求API用户键入“*”,即typedef结构,而不是指向结构的指针。这是GLib中广泛使用的样式,它是更受欢迎的C栈之一。

它很好用,因为 很重要,知道你是否有指向结构或结构本身的指针。例如,您可以在类型的变量中存储NULL吗?如果隐藏对象是指针,则必须创建特殊的NIL_NODE或其他值来替换NULL。如果你只是把它作为一个指针,那么人们可以像对待它那样对待它。

另一个重要的好处是能够将实际的struct定义放在私有的地方,即在.c文件而不是在头文件中。您只需将typedef放在标头中,同时保持结构本身对API用户不透明。这要求人们只使用您提供的导出方法来操作结构。这也意味着如果更改结构字段,则不必重建世界。

采用这种方法的另一个原因是,有时你确实想要一个可以复制的结构,你仍然想要输入它。拿一个像GdkPoint这样的东西:

  typedef struct {
     int x, y;
  } GdkPoint;

这里允许直接进行struct访问很有用,例如:

 GdkPoint point = { 10, 10 };
 GdkPoint copy = point;
 do_stuff_with_point(&copy);

但是,如果您的约定是“GdkPoint”typedef将是一个指针,那么您将不得不一致。

如果您可以告诉什么是指针和什么不是,那么代码就更清楚了,如果您不在头文件中放置结构定义,代码会更好地封装(对于表示抽象,不透明数据类型的结构,这可能是最常见的一种)。

C数据类型的默认模板在标题中是这样的:

typedef struct MyType MyType;
 MyType* my_type_new(void);
 void    my_type_unref(MyType *t);
 void    my_type_ref(MyType *t);

然后是.c文件中的实际“struct MyType”,以及该类型的new,unref和任何操作。

例外的是Point,Rectangle,Color等类型,它是“普通旧数据”并且需要直接字段访问;如果您不需要引用计数,则另一种变体是使用my_type_free()而不是_unref()。

无论如何,这是一种风格,基本上是GLib风格,它被广泛使用并且已知效果很好。

答案 1 :(得分:1)

我更喜欢第一种风格,因此很清楚哪些类型是对象,哪些类型是指针。但我发现C指针很容易理解/解释,显然很多人都没有。因此,如果您认为阅读代码库的大多数人都不会理解指针,请在任何地方使用typedef STRUCT_FOO *PSTRUCT_FOO,就像Win32 API一样。

答案 2 :(得分:0)

考虑使用以下两种方法:

typedef struct list_node Node;
typedef Node* ListHead;

答案 3 :(得分:0)

只要标识符清楚它是一个指针然后没有坏处(我个人更喜欢后缀ala _Pointer或_Ptr,但任何适合项目)。也就是说,对于纯C代码,避免显式*没有实际好处。对于混合C / C ++环境或纯C ++,我经常看到typedef指针用于指向合理化/合理化的指针,以便于转换,使用和切换智能指针类型。这可能有些道理,但我从未发现自己想要采用这种做法。

答案 4 :(得分:0)

typedef int * ptr_int; ptr_int x,y,z;

程序员可能会感到困惑的是,所有三个x,y,z都是int *类型,即 指向int。 但在Reality中,只有x是int *类型y,z是简单的int。

因为ptr_int x,y,z;等于int * x,y,z; 不是int * x,* y,* z;

所以, typedef也会给程序员带来困惑,并可能导致错误和错误。