【问题标题】:Why not using a typedef for a struct in C? [closed]为什么不对 C 中的结构使用 typedef? [关闭]
【发布时间】:2012-09-14 01:16:33
【问题描述】:

我正在研究一个用于 ARM 低功耗设备的 C 应用程序,我首先有这段代码

struct state {
    float position;
    int dummy;
};

注意这个结构没有定义一个新类型,我也注意到在后面的代码中这个结构是这样使用的

struct state mystate;

这对我来说很奇怪,不方便,不灵活,并且有 1 个额外的无用关键字,我可以很容易地避免首先使用 typedef 作为结构。

这是一个对这个应用程序的业务逻辑至关重要的结构,在源代码中也被大量使用。

不将typedef 与最终用作类型的结构一起使用是有特殊原因的吗?

【问题讨论】:

  • 这真的与电源甚至ARM无关。这是一个 C 语法约定。
  • 好吧,如果输入struct 太麻烦,您仍然可以自己输入typedef
  • Typedef 填充了命名空间。程序员有一个大约 7 个标识符的“心理命名空间”。关键字不算。对于人类读者,“struct”是一个 0 字节的标记。
  • 我将 typedef 用于这样的结构,因为我认为这样的代码更具可读性。
  • 首先,这是一个重复的问题。其次,这是一个宗教问题。那些说 struct 的 typedef 不好的人有非常强烈的解释,但解释不充分。如果您认为他们的解释站得住脚,但无论如何还是希望避免 struct 噪音,那么使用 C++ 编写代码,这使得 typedef(因此 struct)变得多余。

标签: c struct typedef


【解决方案1】:

我认为 typedef 有害。我认为它几乎总是被误用。在我看来,它很有用,并且只有在底层类型完全抽象时才有用 - 例如所有的操作都是通过函数。否则,底层类型不会被抽象——用户仍然必须知道它是什么,才能理解代码——所发生的只是代码可读性受损,类型命名空间没有获得收益(对于类型未正确抽象)扩展。

在我看来,几乎所有 typedef 的使用都缺乏对它带来的问题以及应该如何使用它的理解。

【讨论】:

  • 我刚刚在这个讨论中读到 typedef 只是抽象的标签,它们在什么方面可能会出现问题?
  • 只有有抽象才有抽象。考虑。假设你 typedef 一个整数。然后,您稍后使用加法运算符。 你刚刚破坏了抽象。用户必须知道底层类型,否则他无法理解代码 - 所以他现在必须记住另一种类型。这种失败是普遍存在的。我见过代码库,其中 typedef 几十种类型,然后打破抽象 - 噩梦。 typedef 唯一真正的抽象是当所有操作都通过函数调用发生时;用户永远不必知道底层类型。
  • @Jim:我认为将其称为宗教问题是盲目的。事实上,它不是——有一组明确的优点、缺点和误用。整数示例说明了对违反抽象的滥用,这是 typedef 的主要失败;所以这是一回事。据我所知,对结构使用 typedef 是没有道理的。该结构已经有一个类型,因此不需要 typedef;不完整的类型提供了抽象。 typedef 对结构体的唯一作用是增加代码的逻辑复杂度。
  • '我认为将其称为宗教问题是盲目的'——你错了,这是自找的。 '所以这是一回事' - 正如我所说,与OP的问题无关。 '据我所知,对结构使用 typedef 没有任何理由'——它有 OP 所述的明显理由......它避免了对结构噪音词的需要。 'typedef 对结构的唯一影响是增加代码的逻辑复杂性' - 它没有这样的事情;它在代码中添加了两个标记,同时允许删除许多其他标记,并且对逻辑没有影响。我的最后一句话。
  • 不,在 typedefs 后面抽象类型的想法是在程序中引入语义。 size_toff_t 甚至 time_t 是类型定义的基本类型,但它们在程序中引入了更高级别的含义。这会增加(通常显着)程序的可读性。
【解决方案2】:

这里没有提到的一个小细节,来自 C 标准。

6.7.7.3 [...] typedef 声明不引入新类型,仅引入指定类型的同义词。

你可以用它来抽象一些细节,但是当有人走到只允许函数调用的极端时,我想知道他们是如何分配内存的,size_t 以及它是无符号 int 类型的泄漏知识必要的。

鉴于它只是一个别名,我在使用 typedef 作为快捷方式也没有任何问题,例如省略任何地方都需要的附加关键字。我不喜欢重复的样板代码,隐藏它会使代码更短。您应该小心一点,以免影响清晰度和可读性,因此我也更喜欢始终保持命名空间清洁。我觉得这很糟糕:

typedef struct state {
    float position;
    int dummy;
} state;

并且更喜欢这样的东西:

typedef struct s_state {
    float position;
    int dummy;
} t_state;

【讨论】:

  • 您根本不需要命名结构...typedef struct { float position; int dummy; } State; ...因此您只需在结构声明中添加一个标记,并从每次使用该类型中删除一个标记。这显然是明智的做法,纯粹是语法问题,没有提出有效的反对意见。 (对其他一些 typedef 的反对可能是有效的,但与 OP 关于 struct 的问题无关。)
【解决方案3】:

这主要是为了清楚起见。在实践中,人们普遍认为,如果您必须使用 struct 关键字,您应该自己操作内部数据。当结构是 typedef 时,它隐藏了实际的类型,并且操作应该由函数来完成。这是一个并不总是遵循的约定,其他人只是保留 struct 关键字以将其与不透明类型区分开来。

【讨论】:

  • 不完整类型也可以用作不透明类型。无需额外费用(也无需透露内部结构)
  • @wildplasser:完全正确。我不喜欢 typdefs。它们只有在底层类型被完全抽象时才有用,例如由并且仅由功能操作 - 这几乎永远不会发生。据我所知,人们使用 typdef 是因为他们看到其他人使用它,但不了解它的问题或应该如何使用它。
  • 我认为我们同意。函数指针就是一个明显的例子。但这主要是由于需要精神健全;-)
  • Typedef 对于锁类型 (spinlock_t)、pthread (pthread_t) 等是有意义的……当所有操作都通过 API 完成并且您基本上需要对实际数据的“句柄”时。问题主要是关于结构和类型定义。
【解决方案4】:

是否使用typedef 是个人喜好。就个人而言,我只将typedef 用于复杂的指针类型或函数指针。

当你声明一个结构时,你也声明了一个类型,即struct structName。 typedef 所做的只是允许您在这种情况下取​​出定义的struct 部分,这不是必需的。这与低功耗设备完全无关。

【讨论】:

  • 呜呼!我刚刚从这篇文章中获得了 20k 代表!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-22
  • 2012-06-14
  • 2020-07-29
  • 1970-01-01
  • 1970-01-01
  • 2011-10-12
  • 2015-12-01
相关资源
最近更新 更多