_t(下划线-t)后面的类型代表什么?

这似乎是一个简单的问题,但我用Stack Overflow搜索或谷歌找不到它。类型后跟_t是什么意思?如

int_t anInt;

我在C代码中经常看到这种情况,这些代码是为了紧密地处理硬件——我忍不住认为它们是相关的。

117667 次浏览

意思是类型。size_t是大小类型。

这只是一个惯例,意思是“类型”。它对编译器没有任何特殊意义。

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


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

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

对于硬件接口代码,这是一个特别重要的考虑因素,这可能就是为什么您第一次注意到这里的约定。

正如Douglas Mayle所指出的,它基本上表示类型名。因此,以'_t'结束变量或函数名是不明智的,因为它可能会引起一些混乱。除了size_t, C89标准还定义了wchar_toff_tptrdiff_t,可能还有一些我忘记了的。C99标准定义了很多额外的类型,比如uintptr_tintmax_tint8_tuint_least16_tuint_fast32_t等等。这些新类型在size_t0中正式定义,但最常见的情况是使用size_t1,其中包括size_t0(对于标准C头文件来说不常见)。它(size_t1)还定义了与size_t4和size_t5一起使用的宏。

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

但是,你也应该注意到POSIX定义了很多以'_t'结尾的额外类型名,而保留后缀用于实现。这意味着如果您在posix相关的系统上工作,那么使用约定定义自己的类型名是不明智的。我工作的系统已经做到了(超过20年);我们经常会因为系统定义的类型与我们定义的名称相同而出错。

它是数据类型的标准命名约定,通常由typedefs定义。很多处理硬件寄存器的C代码使用c99定义的固定大小有符号和无符号数据类型的标准名称。作为约定,这些名称在标准头文件(stdint.h)中,并以_t结尾。

_t本身没有任何特殊含义。但在typedef的后缀中添加_t已成为常用用法。

您可能更熟悉变量命名的常见C实践…这类似于在指针前面加一个p,在全局变量前面加一个下划线(这种情况不太常见),以及使用变量名ijk作为临时循环变量。

在字符大小和顺序很重要的代码中,通常使用显式的自定义类型,例如BYTE WORD(通常是16位)DWORD(32位)。

int_t不是很好,因为不同平台的int定义不同——那么你遵从谁的int呢?(尽管现在大多数以pc为中心的开发都将int视为32位,但许多非pc开发仍然将int视为16位)。

关于这个问题有一些很好的解释。再补充一个重新定义类型的原因:

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

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

例子:

typedef unsigned long dc_uint32_t;

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

GCC只是将以_t结尾的名称添加到您可能不使用的保留名称空间中,以避免与Standard C和POSIX (GNU C库手册)的未来版本冲突。经过一些研究,我终于在POSIX标准1003.1中找到了正确的参考:B.2.12数据类型(卷:基本原理,附录:B.系统接口原理,章节:B.2基本概况):

< p > 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编码风格(第5章)指南。有一些很好的理由不使用typedef。希望这对你有所帮助!

例如,在C99中,/usr/include/ stdt .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定义。