_t(下划线-t)后跟的类型代表啥?

Posted

技术标签:

【中文标题】_t(下划线-t)后跟的类型代表啥?【英文标题】:What does a type followed by _t (underscore-t) represent?_t(下划线-t)后跟的类型代表什么? 【发布时间】:2010-09-18 21:46:24 【问题描述】:

这似乎是一个简单的问题,但我无法通过 Stack Overflow 搜索或 Google 找到它。 _t 后面的类型是什么意思?比如

int_t anInt;

我在与硬件密切相关的 C 代码中看到了很多 — 我不禁认为它们是相关的。

【问题讨论】:

int_t 在哪里定义?如果总是定义为int,那就没用了;直接使用int 会更清晰。如果它并不总是被定义为int(比如说,它可能是long intshort int),那么它就是一个选择不当且令人困惑的名称。 【参考方案1】:

正如 Douglas Mayle 所说,它基本上表示类型名称。因此,不建议您使用 '_t' 结束变量或函数名称,因为这可能会引起一些混乱。除了size_t,C89 标准还定义了wchar_toff_tptrdiff_t,可能还有一些我已经忘记的。 C99标准定义了很多额外的类型,如uintptr_tintmax_tint8_tuint_least16_tuint_fast32_t等。这些新类型在<stdint.h> 中正式定义,但大多数情况下您会使用<inttypes.h>,它(通常用于标准C 头文件)包括<stdint.h>。它 (<inttypes.h>) 还定义了用于 printf()scanf() 的宏。

正如 Matt Curtis 所指出的,后缀对编译器没有意义;这是一个以人为本的约定。

不过,您还应该注意POSIX 定义了很多以'_t' 结尾的额外类型名称,并且保留了后缀 用于实现。这意味着,如果您正在使用与 POSIX 相关的系统,那么使用约定定义您自己的类型名称是不明智的。我工作的系统已经做到了(超过 20 年);我们经常被定义与我们定义的名称相同的类型的系统绊倒。

【讨论】:

操作系统和通用运行时库定义具有通用名称的类型似乎是合理的;但是您公司的类型不应该也带有前缀或其他东西吗? 我在 typedef 上使用 _type 而不是 _t 正是为了避免这种情况。 @Jonathan Leffler -- 你会为用户定义的类型使用什么命名约定? @Andrew:如果您有一个方便的缩写用作前缀,那么您可以安全地使用abbr_xxxxx_t 类型名称。如果没有这样的前缀,您可能随时会被抓住。通常,标准化的 _t 类型全部使用小写(FILEDIR 是两个例外,两次 - 全部大写,并且没有 _t),因此您可以使用 CamelCase_t 安全性适中,带有或没有领先的上限。我主要工作的系统往往很危险,无论如何都使用_t,但它有时会咬我们。我倾向于在自己的工作中使用不带后缀的CamelCase;我的函数通常都是小写的。 @JonathanLeffler,我已经开始使用该约定,CamelCase 用于类型,lower_case 用于函数。我搜索了这个问题,希望我不是唯一一个。感谢您的验证!【参考方案2】:

这是用于命名数据​​类型的约定,例如typedef

typedef struct char* model; int year; ... car_t;

【讨论】:

不要为自己的类型使用_t后缀,因为它们在某些标准中是保留的,最好使用_T。另外,永远不要typedef 匿名struct,转发声明这个struct 将变得不可能。给struct 一个名字,或者根本不使用typedef 补充 12431...(我上面的那个人)所说的,一般来说,你应该永远不要 typedef 指针和结构/联合。这样做会造成混淆,并且只会混淆类型信息。 struct foo f;union userinput *ui_ptr;foo f;userinput ui; 更清晰、更容易理解。我知道有一个简短的类型名称很诱人,但不要。函数指针是 IMO 可以使用的一个例外,例如typedef void (*foobarfn)(struct foobar *); ... foobarfn my_callback = find_response(some_input);【参考方案3】:

_t 通常包装一个不透明的类型定义。

GCC 只是将以 _t 结尾的名称添加到您可能不使用的保留命名空间中,以避免与标准 C 和 POSIX (GNU C library manual) 的未来版本发生冲突。经过一番研究,我终于在POSIX Standard 1003.1中找到了正确的参考:B.2.12 Data Types(卷:Rationale,附录:B. Rationale for System Interfaces,章节:B.2 General Information):

B.2.12 数据类型定义类型 本节中定义的附加类型以“_t”结尾的要求是由命名空间污染问题引起的。很难在一个头文件中定义一种类型(该类型不是 POSIX.1-2017 定义的类型)并在另一个头文件中使用它而不在程序的名称空间中添加符号。为了允许实现者提供他们自己的类型,所有符合要求的应用程序都必须避免以“_t”结尾的符号,这允许实现者提供额外的类型。由于类型的主要用途是定义结构成员,可以(并且在许多情况下必须)将其添加到 POSIX.1-2017 中定义的结构中,因此对其他类型的需求非常迫切。

简而言之,标准表示很有可能扩展标准类型的列表,因此标准限制 _t 命名空间供自己使用。

例如,您的程序匹配 POSIX 1003.1 第 7 期,并且您定义了一个类型 foo_tPOSIX 1003.1 第 8 版 最终以新定义的类型 foo_t 发布。您的程序与新版本不匹配,这可能是个问题。限制 _t 的使用会阻止重构代码。因此,如果您的目标是符合 POSIX 标准,则绝对应该避免使用标准规定的 _t

旁注:就个人而言,我尝试坚持使用 POSIX,因为我认为它为干净的编程提供了良好的基础。此外,我非常喜欢Linux Coding Style (chapter 5) 指南。不使用 typedef 有一些很好的理由。希望对您有所帮助!

【讨论】:

【参考方案4】:

它是数据类型的标准命名约定,通常由 typedefs 定义。许多处理硬件寄存器的 C 代码使用 C99 定义的标准名称来表示有符号和无符号的固定大小数据类型。按照惯例,这些名称位于标准头文件 (stdint.h) 中,并以 _t 结尾。

【讨论】:

【参考方案5】:

_t 本身并没有任何特殊含义。但是将_t 后缀添加到typedef 中已成为一种常见的用法。

你可能更熟悉变量命名的常见 C 实践......这类似于将 ap 放在前面作为指针的常见做法,并在全局变量前面使用下划线(这有点不太常见),并将变量名称 ijk 用于临时循环变量。

在字长和顺序很重要的代码中,使用显式的自定义类型是很常见的,例如BYTEWORD(通常为 16 位)DWORD(32 位)。

int_t 不太好,因为int 的定义因平台而异——那你符合谁的int? (尽管如今,大多数以 PC 为中心的开发都将其视为 32 位,但非 PC 开发的许多东西仍将 int 视为 16 位)。

【讨论】:

【参考方案6】:

这意味着类型。 size_t 是尺寸类型。

【讨论】:

【参考方案7】:

这只是一个约定,意思是“类型”。这对编译器没有什么特别的意义。

【讨论】:

【参考方案8】:

关于这个主题有一些很好的解释。只是为了添加重新定义类型的另一个原因:

在许多嵌入式项目中,所有类型都被重新定义,以正确说明类型的给定大小并提高跨不同平台(即硬件类型编译器)的可移植性。

另一个原因是让您的代码可跨不同的操作系统移植,并避免与您在代码中集成的操作系统中的现有类型发生冲突。为此,通常会添加一个唯一(尽可能)的前缀。

例子:

typedef unsigned long dc_uint32_t;

【讨论】:

【参考方案9】:

如果您正在处理硬件接口代码,您正在查看的代码的作者可能已将 int_t 定义为特定大小的整数。 C 标准没有为 int 类型分配特定的大小(这可能取决于您的编译器和目标平台),使用特定的 int_t 类型可以避免这种可移植性问题。

这对于硬件接口代码来说是一个特别重要的考虑因素,这可能是您首先注意到那里的约定的原因。

【讨论】:

这不是很好的做法,我希望人们定义 [u]int_[32 16 8]_t 以明确您定义的大小。 你说的很对,"int_t" 本身就告诉程序员它是用户定义的类型,但不是真正的类型!【参考方案10】:

例如在 C99 中,/usr/include/stdint.h:

typedef unsigned char           uint8_t;
typedef unsigned short int      uint16_t;
#ifndef __uint32_t_defined
typedef unsigned int            uint32_t;
# define __uint32_t_defined
#endif
#if __WORDSIZE == 64
typedef unsigned long int       uint64_t;
#else
__extension__
typedef unsigned long long int  uint64_t;
#endif

_t 始终表示由 typedef 定义。

【讨论】:

以上是关于_t(下划线-t)后跟的类型代表啥?的主要内容,如果未能解决你的问题,请参考以下文章

Python 类型提示:Callable 后跟 TypeVar 是啥意思?

以“_”开头的变量是啥类型变量?

正则表达式

第四章 T-SQL编程

scala - 泛型中的任何与下划线

_T 在 CString 中代表啥