如果我在 C 或 C++ 中执行 `typedef`,我啥时候应该在 typedef'ed 类型的末尾添加 `_t`? [复制]

Posted

技术标签:

【中文标题】如果我在 C 或 C++ 中执行 `typedef`,我啥时候应该在 typedef\'ed 类型的末尾添加 `_t`? [复制]【英文标题】:If I do a `typedef` in C or C++, when should I add `_t` at the end of typedef'ed type? [duplicate]如果我在 C 或 C++ 中执行 `typedef`,我什么时候应该在 typedef'ed 类型的末尾添加 `_t`? [复制] 【发布时间】:2011-03-14 14:44:36 【问题描述】:

我很困惑何时应该将尾随 _t 添加到 typedef'ed 类型?

例如,我应该这样做:

typedef struct image image_t;

或者这个:

typedef struct image image;

一般规则是什么?

另一个例子,我应该这样做:

typdef enum  ARRAY_CLOSED, ARRAY_OPEN, ARRAY_HALFOPEN  array_type_t;

或者这个:

typdef enum  ARRAY_CLOSED, ARRAY_OPEN, ARRAY_HALFOPEN  array_type;

请赐教。

谢谢,博达·赛多。

【问题讨论】:

从不。以_t 结尾的类型名称被某些标准保留(不确定是哪个)。不管你做什么,不要做_type_t。选择_type_t(或其他),但请不要堆叠它们。这简直是​​愚蠢的。 @Billy - 搜索了一下,我认为它是 POSIX。向下滚动,James McNellis 击败了我。 @Billy @Chris:我没有参考链接,抱歉;限制和引用可以在What are the rules about using an underscore in a C++ identifier?的答案中找到 _t 结尾的标识符在POSIX 中保留:opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html。并不是说我很在意(我经常输入以_t 结尾的名字)。 @MichaelBurr 那篇文章说“实现可能会在下表中显示的标头中添加符号,前提是这些符号的标识符:[...] 以表中保留后缀表示的字符串结尾并且不要使用保留的前缀 posix_、POSIX_ 或 POSIX,只要保留的后缀位于名称中被实施认为重要的部分。”所以表格是说你可以使用_t来定义在任何标题中的类型。 【参考方案1】:

我个人鄙视_t 约定。但是,只要您始终如一,那真的没关系。

请注意(正如此处的其他答案所示)如果您正在编码其他标准,例如 POSIX,您需要在使用此类名称之前检查该标准是否可以。

【讨论】:

【参考方案2】:

在 POSIX 中,以 _t 结尾的名称是保留的,因此如果您的目标是 POSIX 系统(例如 Linux),则不应以 _t 结尾。

【讨论】:

根据经验,您通常可以在很长一段时间内侥幸逃脱 - 但如果您移植到新平台或平台的新版本并发现冲突,您将无法在任何人身上卷土重来。所以,不使用后缀是最安全的。 许多损坏的 API 也是如此。这并不意味着您应该复制他们的不良行为。 @doc:标准 C 库不使用 C++ 命名空间。 @JamesMcNellis 我发现从“实施者可以在任何地方使用_t”到“没有其他人可以使用_t”的信念飞跃太大了。除非有文档专门保留_t 供 POSIX 使用,否则我认为此表已被误解。 @user23743 “实现者可以在任何地方使用_t”表示他们可以使用_t 定义宏,这意味着您对_t 的任何使用都需要进行宏替换。【参考方案3】:

我使用_t 后缀作为枚举和原始类型,以将它们与变量区分开来。我将它们放入命名空间,所以我不关心_t 的保留。

为了证明这一点。很多时候,变量名是对 typedefed 类型的暗示。像std::size_t size;array_t array 等。我发现当类型包含_t 后缀时,为变量取合适的名称更容易。它还提醒我,它是一个类型定义的原语,而不是其他诸如类之类的野兽。

【讨论】:

size_t size_t = 0; 在 C 中是合法的 - 它声明了一个名为 size_t 的变量,其类型为 size_t。类型和变量之间的冲突无关紧要。 然后代码的可读性就进入了空间。这同样适用于size size = 0; @Chris Lutz:你读过“区分变量”吗?【参考方案4】:

为你的类型选择好的名字,就像你应该为你的变量、函数和其他任何东西一样。一个好名字没有嵌入冗余信息,这会使代码更难阅读——如果你有一个好名字,_t 永远不会帮助你。

顺便说一句:typedef image image; 没有任何意义,因为它只是让 image 成为自身的 typedef。

【讨论】:

他使用的例子是typedef struct image image,这在C语言中很有用。在C++中,struct image变量可以声明为image x;,但在C语言中,你必须声明它们struct image x;所以C程序员使用上面的方法来简化常用类型的struct 声明。 他没有写typedef image image——他写的是typedef struct image image。这在 C 中很常见。 以这种方式对未命名的结构进行 typedef 也是很常见的。 @Chuck、Chris Lutz 和 Spidey:他做到了——我的疏忽。【参考方案5】:

什么时候应该使用_t?绝不?它由主要标准 (POSIX) 保留,即使现在不是,您的代码也可能有一天会在 POSIX 环境中使用,因此使用_t 是个坏主意。

我会进一步说,过度使用typedef 通常是不好的。如果您的类型是structunionenum,请在声明变量时使用这些关键字,这会使您的代码更清晰。 typedef 的使用最好保留在您想要使底层类型不可见以用于抽象/封装目的时。来自标准 C 的几个很好的例子是 size_tint32_tmbstate_t 和 stdio FILE

typedef 的一些最严重的滥用是由 Windows API(WORDDWORDINTLPSTR 等)和 glib(gintgchar 等) .以相同的预期用途复制标准 C 类型只会造成混淆,并且会通过使用这些非标准类型名称污染所有代码来将开发人员锁定在您的库/平台中。

【讨论】:

同意 Windows API 部分,但不同意 glib,就此而言,Qt 也是如此:当支持大量平台时,有必要知道您正在处理什么类型,以及gint/qint 可以有不同的底层类型。另外:没有人会强迫使用 glib/Qt 的开发人员使用这些内部类型,因为它们只是 typedefs,您可以轻松地使用 int 而不是 gint(当然,对于您的非异国平台,它们是相同的)。 除非你能提供真正有用的证据,否则我认为你完全错了。 gint 未定义为任何特定大小的整数;它和int 一样随意。如果 glib API 函数需要特定大小,那么它们应该只使用该类型:例如,int32_t 如果需要 32 位整数,size_t 如果需要对象大小或数组索引等。 @doc,不,C 只保留一组特定的类型名称,其中一些以_t 结尾。 POSIX 绝对保留任何以_t 结尾的名称以备将来使用。在 C++ 中,只要您使用将标准类型隔离到命名空间的标头,这可能不是问题... 请注意,Windows API 这样做的原因是 Windows API 类型应该是它们自己的类型;可以从 C 以外的语言调用。因此,它的 API 调用不能根据 C 类型定义。 *nix 操作系统通过告诉所有非 C 语言下地狱来避免这种情况;但非 C 语言在 Windows 上比在 Unix 上更流行。 @rubenvb Qt 不是这样。它尽可能使用intboolconst char * 等标准类型。当需要解决某些问题时使用诸如qreal 之类的类型(qreal 上的 Qt 手册:“Typedef for double 在所有平台上,除了那些使用 ARM 架构的 CPU。在基于 ARM 的平台上,qreal 是 float 的 typedef出于性能原因”)。【参考方案6】:

我使用后缀来增加可读性:_t 表示 typedef,_e 表示自 25/30 年以来的枚举......有时我在 typedef 定义结构时使用 _st。

我认为这是让代码可读和标准化的好习惯,然后我发现使用后缀是正确的!此外,到目前为止,我还没有找到任何 POSIX 官方文档说明后缀 _t 是保留的。

旧的 stdio.h 包含 _t ...参见:grep -i "_t;" stdio.h :) 我认为 POSIX 标准比 C 标准“有点”年轻!

【讨论】:

这个答案提到了 POSIX 标准中的引用:***.com/a/12727104/1404081(“所有符合标准的应用程序都必须避免以‘‘_t’’结尾的符号”)。

以上是关于如果我在 C 或 C++ 中执行 `typedef`,我啥时候应该在 typedef'ed 类型的末尾添加 `_t`? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥 C 和 C++ 关键字“#defined”或“typedefed”也是它们的大写版本?

typedef struct 与 struct

C++ 中不寻常的 typedef 使用

typedef的用法结构体

重复的 typedef - 在 C 中无效但在 C++ 中有效?

将函数指针分配给 constexpr 结构中的 typedef 函数的正确 C++ 方法是啥?