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


261

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

int_t anInt;

我在用C语言处理硬件的过程中看到了很多东西,我不禁认为它们之间存在关联。


3
在哪里int_t定义?如果始终将其定义为int,则它没有用;int直接使用更加清晰。如果不总是将其定义为int(例如,如果可能是long intshort int),则它是一个选择不当且令人困惑的名称。
基思·汤普森

Answers:


213

正如道格拉斯·梅尔(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年);我们经常会被系统定义类型与我们定义的名称相同的系统绊倒。


4
OS和通用运行时库用通用名称定义类型似乎是合理的;但您公司的类型是否也应该不带前缀或其他前缀?
Toybuilder

17
为了避免这种情况,我在typedef上使用_type而不是_t。
CesarB

4
@Jonathan Leffler-用户定义类型将使用什么命名约定?
J.安德鲁·劳克林(Andrew Laughlin)

15
@Andrew:如果您可以方便地使用缩写作为前缀,那么使用abbr_xxxxx_t类型名称可能是安全的。没有这样的前缀,您可能会随时被抓。通常,标准化_t类型使用所有小写字母(FILE并且DIR是两个例外,两次,两次-所有大写字母,没有no _t),因此无论是否使用CamelCase_t前导大写字母,都可以在中等安全性下使用。我主要研究的系统_t无论如何都会危险地生活和使用,但有时却使我们感到痛苦。我倾向于在CamelCase没有后缀的情况下使用自己的作品。我的函数通常都是小写的。
乔纳森·莱夫勒

5
@JonathanLeffler,我开始使用该约定,CamelCase用于类型,lower_case用于函数。我搜寻了这个问题,希望我不是唯一的一个。感谢您的验证!
奥斯丁·穆林斯

50

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


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


43

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

GCC只会将以结尾的名称添加_t到您可能不会使用的保留名称空间中,以避免与Standard C和POSIX的未来版本发生冲突(GNU C库手册)。经过一些研究,我终于在POSIX标准(1003.1,基本原理(信息性))中找到了正确的参考:

B.2.12数据类型

名称空间污染问题提示了本节中定义的其他类型以“ _t”结尾的要求。在一个头文件中定义一个类型(其中该类型不是IEEE Std 1003.1-2001定义的类型)并在不将符号添加到程序的名称空间的情况下,在另一个头文件中使用它是很困难的。为了允许实现者提供自己的类型,所有符合标准的应用程序都必须避免以“ _t”结尾的符号,从而允许实现者提供其他类型。由于类型的主要用途是结构成员的定义,可以(在很多情况下必须)将其添加到IEEE Std 1003.1-2001中定义的结构中,因此迫切需要其他类型。

简而言之,标准说有很好的机会扩展标准类型的列表,因此标准限制了_t名称空间供其自己使用。

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

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


18

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



11

_t并不具有任何特殊含义。但是,将_t后缀添加到typedef的使用已成为普遍使用。

您可能更熟悉用于变量命名的通用C惯例...这类似于将ap放在指针的前面,并在全局变量的前面使用下划线(这有点少见),这很常见。 ,并使用变量名ij以及k临时循环变量。

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

int_t并不是很好,因为int平台之间的定义各不相同-那么int您遵循的是谁?(尽管现在,大多数以PC为中心的开发将其视为32位,但许多非PC开发人员仍将int视为16位)。



8

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

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

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

例:

typedef unsigned long dc_uint32_t;

7

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

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


1
这不是很好的做法,我希望定义一个[u] int_ [32 16 8] _t来明确您定义的大小。
伊利亚

1
您说得很对,“ int_t”本身告诉程序员这是用户定义的类型,但实际上不是!
格雷格(Greg Hewgill)

0

例如在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定义。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.