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

发布于 2024-07-08 08:25:38 字数 173 浏览 7 评论 0原文

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

int_t anInt;

我在 C 代码中经常看到它与硬件密切相关,我不禁认为它们是相关的。

This seems like a simple question, but I can't find it with the Stack Overflow search or Google. What does a type followed by a _t mean? Such as

int_t anInt;

I see it a lot in C code meant to deal closely with hardware—I can't help but think that they're related.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

仙气飘飘 2024-07-15 08:25:38

正如 Douglas Mayle 所指出的,它基本上表示一个类型名称。 因此,不建议您以“_t”结尾变量或函数名称,因为它可能会导致一些混乱。 除了 size_t 之外,C89 标准还定义了 wchar_toff_tptrdiff_t 以及我可能见过的其他一些标准忘记了。 C99标准定义了很多额外的类型,例如uintptr_tintmax_tint8_tuint_least16_t>uint_fast32_t,等等。 这些新类型在 中正式定义,但大多数情况下您将使用 ,其中(对于标准 C 头文件来说不常见)包括 。 它 () 还定义了与 printf()scanf() 一起使用的宏。

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

但是,您还应该注意 POSIX 定义了许多以 '结尾的额外类型名称_t',并保留后缀以供实现。 这意味着,如果您正在使用 POSIX 相关系统,那么使用约定定义您自己的类型名称是不明智的。 我所开发的系统已经做到了这一点(20 多年了); 我们经常会被系统定义与我们定义的名称相同的类型所困扰。

As Douglas Mayle noted, it basically denotes a type name. Consequently, you would be ill-advised to end variable or function names with '_t' since it could cause some confusion. As well as size_t, the C89 standard defines wchar_t, off_t, ptrdiff_t, and probably some others I've forgotten. The C99 standard defines a lot of extra types, such as uintptr_t, intmax_t, int8_t, uint_least16_t, uint_fast32_t, and so on. These new types are formally defined in <stdint.h> but most often you will use <inttypes.h> which (unusually for standard C headers) includes <stdint.h>. It (<inttypes.h>) also defines macros for use with the printf() and scanf().

As Matt Curtis noted, there is no significance to the compiler in the suffix; it is a human-oriented convention.

However, you should also note that POSIX defines a lot of extra type names ending in '_t', and reserves the suffix for the implementation. That means that if you are working on POSIX-related systems, defining your own type names with the convention is ill-advised. The system I work on has done it (for more than 20 years); we regularly get tripped up by systems defining types with the same name as we define.

要走就滚别墨迹 2024-07-15 08:25:38

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

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

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

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

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

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

The _t usually wraps an opaque type definition.

GCC merely add names that end with _t to the reserved namespace you may not use, to avoid conflicts with future versions of Standard C and POSIX (GNU C library manual). After some research, I finally found the correct reference inside the POSIX Standard 1003.1: B.2.12 Data Types (Volume: Rationale, Appendix: B. Rationale for System Interfaces, Chapter: B.2 General Information):

B.2.12 Data Types
Defined Types
The requirement that additional types defined in this section end in "_t" was prompted by the problem of name space pollution. It is difficult to define a type (where that type is not one defined by POSIX.1-2017) in one header file and use it in another without adding symbols to the name space of the program. To allow implementors to provide their own types, all conforming applications are required to avoid symbols ending in "_t", which permits the implementor to provide additional types. Because a major use of types is in the definition of structure members, which can (and in many cases must) be added to the structures defined in POSIX.1-2017, the need for additional types is compelling.

In a nutshell, the Standard says that there are good chances of extending the Standard types' list, therefore the Standard restricts the _t namespace for its own use.

For instance, your program matches POSIX 1003.1 Issue 7 and you defined a type foo_t. POSIX 1003.1 Issue 8 is eventually released with a newly defined type foo_t. Your program does not match the new version, which might be a problem. Restricting the _t usage prevents from refactoring the code. Thus, if you aim to a POSIX compliancy, you should definitely avoid the _t as the Standard states it.

Side note: personally, I try to stick to POSIX because I think it gives good basics for clean programming. Moreover, I am pretty fond of Linux Coding Style (chapter 5) guidelines. There are some good reasons why not using typedef. Hope this help!

拔了角的鹿 2024-07-15 08:25:38

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


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

It's a convention used for naming data types, e.g with typedef:


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

桜花祭 2024-07-15 08:25:38

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

It is a standard naming convention for data types, usually defined by typedefs. A lot of C code that deals with hardware registers uses C99-defined standard names for signed and unsigned fixed-size data types. As a convention, these names are in a standard header file (stdint.h), and end with _t.

醉城メ夜风 2024-07-15 08:25:38

_t 本质上没有任何特殊含义。 但在 typedef 中添加 _t 后缀已经变得很常见。

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

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

int_t 不太好,因为 int 的定义在不同平台上有所不同——那么你遵循谁的 int 呢? (尽管现在,大多数以 PC 为中心的开发将其视为 32 位,但许多非 PC 开发的东西仍然将 int 视为 16 位)。

The _t does not inherently have any special meaning. But it has fallen into common use to add the _t suffix to typedef's.

You may be more familiar with common C practices for variable naming... This is similar to how it's common to stick a p at the front for a pointer, and to use an underscore in front of global variables (this is a bit less common), and to use the variable names i, j, and k for temporary loop variables.

In code where word-size and ordering is important, it's very common to use custom defined types that are explicit, such as BYTE WORD (normally 16-bit) DWORD (32-bits).

int_t is not so good, because the definition of int varies between platforms -- so whose int are you conforming to? (Although, these days, most PC-centric development treats it as 32 bits, much stuff for non-PC development still treat int's as 16 bits).

倾城°AllureLove 2024-07-15 08:25:38

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

It's just a convention which means "type". It means nothing special to the compiler.

青芜 2024-07-15 08:25:38

就是类型的意思。 size_t 是尺码类型。

It means type. size_t is the size type.

雪落纷纷 2024-07-15 08:25:38

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

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

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

例子:

typedef unsigned long dc_uint32_t;

There were a few good explanations about the subject. Just to add another reason for re-defining the types:

In many embedded projects, all types are redefined to correctly state the given sizing to the types and to improve portability across different platforms (i.e hardware types compilers).

Another reason will be to make your code portable across different OSs and to avoid collisions with existing types in the OS that you are integrating in your code. For this, usually a unique (as possible) prefix is added.

Example:

typedef unsigned long dc_uint32_t;
身边 2024-07-15 08:25:38

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

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

If you're dealing with hardware interface code, the author of the code you're looking at might have defined int_t to be a specific size integer. The C standard doesn't assign a specific size to the int type (it depends on your compiler and target platform, potentially), and using a specific int_t type would avoid that portability problem.

This is a particularly important consideration for hardware interface code, which may be why you've first noticed the convention there.

独自唱情﹋歌 2024-07-15 08:25:38

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

For example in 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 always means defined by typedef.

本宫微胖 2024-07-15 08:25:38

_t 表示“类型”。 将其与 typedef 一起使用是一种常见的约定。

我已经使用它很多年了,例如,在专业代码库中,如下所示:注意我对 timer_ttimer_error_t 的使用:

typedef struct timer_s 
{ 
    // When the timer was started
    uint32_t start_ticks;
    // How long until the timer expires
    uint32_t timeout_ticks;
    // Whether or not the timer has previously expired without being restarted
    bool expired;
} timer_t;

typedef enum timer_error_e
{
    // No error
    TIMER_ERROR_NONE = 0,
    // You passed in a NULL pointer
    TIMER_ERROR_NULL_POINTER,
    // The timeout value invalid (ex: too large)
    TIMER_ERROR_INVALID_TIMEOUT,
} timer_error_t;

但是,我最近从 @Jonathan Leffler 的回答,POSIX 为其自己的类型保留 _t 后缀,我遇到了问题其中 timer_t 已由 POSIX 定义,从而阻止上面的编译!

G++ 编译时错误:

/usr/include/x86_64-linux-gnu/bits/types/timer_t.h:7:19: note: previous declaration as ‘typedef void* timer_t’
    7 | typedef __timer_t timer_t;
      |                   ^~~~~~~

因此,我切换到这个新约定以避免使用 POSIX 保留的 _t 后缀。 我进行了以下更改,从而删除了对 _t 的使用:

timer_s --> Timer_s
timer_t --> Timer

timer_error_e --> Timer_error_e
timer_error_t --> Timer_error

这是最终结果:

推荐的结构和枚举命名约定,以避免重新定义由 保留的 _t 类型POSIX

typedef struct Timer_s 
{ 
    // When the timer was started
    uint32_t start_ticks;
    // How long until the timer expires
    uint32_t timeout_ticks;
    // Whether or not the timer has previously expired without being restarted
    bool expired;
} Timer;

typedef enum Timer_error_e
{
    // No error
    TIMER_ERROR_NONE = 0,
    // You passed in a NULL pointer
    TIMER_ERROR_NULL_POINTER,
    // The timeout value invalid (ex: too large)
    TIMER_ERROR_INVALID_TIMEOUT,
} Timer_error;

这一新约定避免了重叠使用 _t 的风险。

_t means "type". It's a common convention to use it with typedefs.

I've been using it for years, for instance, in professional code bases, like this: notice my usage of timer_t and timer_error_t:

typedef struct timer_s 
{ 
    // When the timer was started
    uint32_t start_ticks;
    // How long until the timer expires
    uint32_t timeout_ticks;
    // Whether or not the timer has previously expired without being restarted
    bool expired;
} timer_t;

typedef enum timer_error_e
{
    // No error
    TIMER_ERROR_NONE = 0,
    // You passed in a NULL pointer
    TIMER_ERROR_NULL_POINTER,
    // The timeout value invalid (ex: too large)
    TIMER_ERROR_INVALID_TIMEOUT,
} timer_error_t;

However, I recently learned from @Jonathan Leffler's answer that POSIX reserves the _t suffix for its own types, and I ran into the problem where timer_t is already defined by POSIX, preventing the above from compiling!

G++ compile-time error:

/usr/include/x86_64-linux-gnu/bits/types/timer_t.h:7:19: note: previous declaration as ‘typedef void* timer_t’
    7 | typedef __timer_t timer_t;
      |                   ^~~~~~~

So, I'm switching to this new convention to avoid using the _t suffix which is reserved by POSIX. I've made the following changes, thereby removing my usage of _t:

timer_s --> Timer_s
timer_t --> Timer

timer_error_e --> Timer_error_e
timer_error_t --> Timer_error

Here's the final result:

Recommended naming convention for structs and enums to avoid redefining _t types which are reserved by POSIX

typedef struct Timer_s 
{ 
    // When the timer was started
    uint32_t start_ticks;
    // How long until the timer expires
    uint32_t timeout_ticks;
    // Whether or not the timer has previously expired without being restarted
    bool expired;
} Timer;

typedef enum Timer_error_e
{
    // No error
    TIMER_ERROR_NONE = 0,
    // You passed in a NULL pointer
    TIMER_ERROR_NULL_POINTER,
    // The timeout value invalid (ex: too large)
    TIMER_ERROR_INVALID_TIMEOUT,
} Timer_error;

This new convention avoids the risk of having overlapping usages of _t.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文