为什么我们应该在C中经常输入一个结构体?

我看过很多程序,包括下面的结构

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

elem user;

为什么需要这么频繁? 任何特定原因或适用区域?


正如Greg Hewgill所说,typedef意味着您不必再遍布整个地方写struct 。 这不仅可以节省击键次数,还可以使代码更清洁,因为它提供了更多的抽象。

东西喜欢

typedef struct {
  int x, y;
} Point;

Point point_new(int x, int y)
{
  Point a;
  a.x = x;
  a.y = y;
  return a;
}

如果您不需要在整个地方看到“struct”关键字,就会变得更清晰,它看起来更像是您的语言中实际上有一种称为“Point”的类型。 其中,在typedef ,我猜是这样。

另外请注意,尽管您的示例(和我的)省略了命名struct本身,但实际命名它对于您想要提供不透明类型时也很有用。 然后你可以在头文件中找到这样的代码,例如:

typedef struct Point Point;

Point * point_new(int x, int y);

然后在实现文件中提供struct声明:

struct Point
{
  int x, y;
};

Point * point_new(int x, int y)
{
  Point *p;
  if((p = malloc(sizeof *p)) != NULL)
  {
    p->x = x;
    p->y = y;
  }
  return p;
}

在后一种情况下,由于其声明对头文件的用户是隐藏的,因此不能返回按值的点。 例如,这是一项在GTK +中广泛使用的技术。

更新请注意,还有一些高度重视的C项目,其中使用typedef来隐藏struct被认为是一个坏主意,Linux内核可能是最知名的这样的项目。 有关Linus愤怒的单词,请参阅Linux Kernel CodingStyle文档的第5章。 :)我的观点是,这个问题中的“应该”可能不是一成不变的。


有多少人弄错了,真是太神奇了。 请不要在C中使用typedef结构,它会不必要地污染已经在大型C程序中受到污染的全局名称空间。

而且,没有标签名称的typedef'd结构是造成头文件之间不必要的排序关系的主要原因。

考虑:

#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,compiland单元可以包含foo.h以获得FOO_DEF定义。 如果它不试图取消引用foo结构的'bar'成员,那么将不需要包含“bar.h”文件。

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

struct foo *foo;

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

由于命名空间是独立的,因此命名与它们的结构标记名称一致的变量没有冲突。

如果我必须维护你的代码,我将删除你的typedef结构。


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


命名结构的C语言规则有点古怪,但它们非常无害。 然而,当扩展到C ++中的类时,这些相同的规则对于错误爬行没有什么影响。

在C中,名字出现在

struct s
    {
    ...
    };

是一个标签。 标签名称不是类型名称。 鉴于上面的定义,声明如

s x;    /* error in C */
s *p;   /* error in C */

在C中是错误的。你必须把它们写成

struct s x;     /* OK */
struct s *p;    /* OK */

联合和枚举的名称也是标签而不是类型。

在C中,标签不同于其他所有名称(对于函数,类型,变量和枚举常量)。 C编译器在符号表中维护标记,在概念上如果不是与包含所有其他名称的表在物理上分离的话。 因此,C程序有可能在相同范围内同时使用同一个拼写的标记和另一个名称。 例如,

struct s s;

是一个有效的声明,它声明了struct s类型的变量。 这可能不是好的做法,但C编译器必须接受它。 我从来没有看到为什么C这样设计的理由。 我一直认为这是一个错误,但它就是这样。

许多程序员(包括你的真正的)更喜欢将结构名称看作类型名称,所以他们使用typedef为标签定义一个别名。 例如,定义

struct s
    {
    ...
    };
typedef struct s S;

可以让你使用S代替结构体,如

S x;
S *p;

程序不能使用S作为类型和变量(或函数或枚举常量)的名称:

S S;    // error

这很好。

结构体,联合体或枚举定义中的标记名是可选的。 许多程序员将结构定义折叠到typedef中,并完全免除标签,如下所示:

typedef struct
    {
    ...
    } S;

链接的文章还讨论了不需要typedef的C ++行为如何导致细微的名称隐藏问题。 为了避免这些问题,这是一个好主意typedef类和结构在C ++中,也是如此,尽管乍一看这似乎是不必要的。 在C ++中,使用typedef ,名称隐藏成为编译器告诉您的错误,而不是潜在问题的隐藏源。

链接地址: http://www.djcxy.com/p/78661.html

上一篇: Why should we typedef a struct so often in C?

下一篇: Can typedef used for vector in general?