Was bedeutet ein Typ gefolgt von _t (Unterstrich-t)?

261

Dies scheint eine einfache Frage zu sein, aber ich kann sie mit der Stapelüberlaufsuche oder Google nicht finden. Was bedeutet ein Typ, gefolgt von einem _tMittelwert? Sowie

int_t anInt;

Ich sehe es oft in C-Code, der eng mit Hardware umgehen soll - ich kann nicht anders, als zu glauben, dass sie verwandt sind.

Kevin Griffin
quelle
3
Wo ist int_tdefiniert? Wenn es immer definiert ist als int, ist es nicht nützlich; Es ist viel klarer, intdirekt zu verwenden . Wenn es nicht immer definiert ist als int(sagen wir, ob es sein könnte long intoder short int), dann ist es ein schlecht gewählter und verwirrender Name.
Keith Thompson

Antworten:

213

Wie Douglas Mayle bemerkte, bezeichnet es im Grunde einen Typnamen. Infolgedessen wäre es nicht ratsam, Variablen- oder Funktionsnamen mit ' _t' zu beenden , da dies zu Verwirrung führen könnte. Neben size_t, die C89 - Standard definiert wchar_t, off_t, ptrdiff_tund wahrscheinlich einige andere habe ich vergessen. Der C99 - Standard definiert eine Menge von zusätzlichen Typen, wie uintptr_t, intmax_t, int8_t, uint_least16_t, uint_fast32_t, und so weiter. Diese neuen Typen werden formal in definiert, <stdint.h>aber meistens verwenden Sie <inttypes.h>welche (ungewöhnlich für Standard-C-Header) <stdint.h>. Es ( <inttypes.h>) definiert auch Makros zur Verwendung mit printf()und scanf().

Wie Matt Curtis bemerkte, hat der Compiler im Suffix keine Bedeutung. Es ist eine menschenorientierte Konvention.

Beachten Sie jedoch auch, dass POSIX viele zusätzliche Typnamen definiert, die mit ' _t' enden , und das Suffix für die Implementierung reserviert . Das heißt, wenn Sie an POSIX-bezogenen Systemen arbeiten, ist es nicht ratsam, Ihre eigenen Typnamen mit der Konvention zu definieren. Das System, an dem ich arbeite, hat es geschafft (seit mehr als 20 Jahren); Wir werden regelmäßig von Systemen gestolpert, die Typen mit demselben Namen definieren, den wir definieren.

Jonathan Leffler
quelle
4
Es erscheint vernünftig, dass Betriebssystem- und allgemeine Laufzeitbibliotheken Typen mit generischen Namen definieren. Aber sollte Ihrem Unternehmenstyp nicht auch ein Präfix oder etwas vorangestellt werden?
Toybuilder
17
Ich verwende _type anstelle von _t in meinen typedefs genau, um dies zu vermeiden.
CesarB
4
@ Jonathan Leffler - Welche Namenskonvention würden Sie für benutzerdefinierte Typen verwenden?
J. Andrew Laughlin
15
@ Andrew: Wenn Sie eine bequeme Abkürzung als Präfix haben, können Sie sicher Typnamen verwenden abbr_xxxxx_t. Ohne ein solches Präfix können Sie jederzeit erwischt werden. Im Allgemeinen verwenden die standardisierten _tTypen alle Kleinbuchstaben ( FILEund es DIRgibt zwei Ausnahmen, zweimal - alle Großbuchstaben und nein _t), sodass Sie sie CamelCase_tmit mäßiger Sicherheit mit oder ohne die führenden Großbuchstaben verwenden können. Das System, an dem ich hauptsächlich arbeite, neigt dazu, gefährlich zu leben und es _ttrotzdem zu benutzen , aber es hat uns gelegentlich gebissen. Ich neige dazu, CamelCaseohne Suffix für meine eigene Arbeit zu verwenden; Meine Funktionen sind normalerweise alle in Kleinbuchstaben.
Jonathan Leffler
5
@ JonathanLeffler, ich habe angefangen, diese Konvention zu verwenden, CamelCase für Typen, Kleinbuchstaben für Funktionen. Ich suchte diese Frage in der Hoffnung, nicht der einzige zu sein. Danke für die Validierung!
Austin Mullins
50

Es ist eine Konvention zum Benennen von Datentypen, z. B typedef.:


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

mmacaulay
quelle
43

Das _tumschließt normalerweise eine undurchsichtige Typdefinition.

GCC fügt lediglich Namen hinzu, die mit _tdem reservierten Namespace enden , den Sie möglicherweise nicht verwenden, um Konflikte mit zukünftigen Versionen von Standard C und POSIX (GNU C-Bibliothekshandbuch) zu vermeiden . Nach einigen Recherchen fand ich schließlich die richtige Referenz im POSIX-Standard (1003.1, Begründung (informativ)):

B.2.12 Datentypen

Die Anforderung, dass zusätzliche in diesem Abschnitt definierte Typen mit '' _t '' enden, wurde durch das Problem der Verschmutzung des Namensraums ausgelöst. Es ist schwierig, einen Typ (wobei dieser Typ nicht durch IEEE Std 1003.1-2001 definiert ist) in einer Header-Datei zu definieren und in einer anderen zu verwenden, ohne dem Namensraum des Programms Symbole hinzuzufügen. Damit Implementierer ihre eigenen Typen bereitstellen können, müssen alle konformen Anwendungen Symbole vermeiden, die mit '' _t '' enden, wodurch der Implementierer zusätzliche Typen bereitstellen kann. Da die Definition von Strukturelementen hauptsächlich von Typen verwendet wird, die zu den in IEEE Std 1003.1-2001 definierten Strukturen hinzugefügt werden können (und in vielen Fällen müssen), ist der Bedarf an zusätzlichen Typen zwingend.

Kurz gesagt, der Standard sagt, dass es gute Chancen gibt, die Liste der Standardtypen zu erweitern, daher beschränkt der Standard den _tNamespace für seine eigene Verwendung.

Zum Beispiel stimmt Ihr Programm mit POSIX 1003.1 Issues 6 überein und Sie haben einen Typ definiert foo_t. POSIX 1003.1 Issues 7 wird schließlich mit einem neu definierten Typ veröffentlicht foo_t. Ihr Programm stimmt nicht mit der neuen Version überein, was möglicherweise ein Problem darstellt. Durch die Einschränkung der _tVerwendung wird verhindert, dass der Code umgestaltet wird. Wenn Sie also eine POSIX-Konformität anstreben, sollten Sie dies unbedingt vermeiden, _twie es der Standard vorschreibt.

Randnotiz: Ich persönlich versuche, mich an POSIX zu halten, weil ich denke, dass es gute Grundlagen für eine saubere Programmierung bietet. Darüber hinaus mag ich die Richtlinien für Linux Coding Style (Kapitel 5) sehr gern . Es gibt einige gute Gründe, warum Sie nicht typedef verwenden. Ich hoffe das hilft!

Benoit
quelle
18

Es ist eine Standard-Namenskonvention für Datentypen, die normalerweise durch typedefs definiert wird. Viele C-Codes, die sich mit Hardwareregistern befassen, verwenden C99-definierte Standardnamen für vorzeichenbehaftete und vorzeichenlose Datentypen mit fester Größe. Konventionell befinden sich diese Namen in einer Standard-Header-Datei (stdint.h) und enden mit _t.

mkClark
quelle
11

Es ist nur eine Konvention, die "Typ" bedeutet. Für den Compiler bedeutet dies nichts Besonderes.

Matt Curtis
quelle
11

Das _that von Natur aus keine besondere Bedeutung. Es ist jedoch üblich geworden, das _tSuffix zu typedefs hinzuzufügen .

Möglicherweise sind Sie mit den gängigen C-Praktiken für die Benennung von Variablen besser vertraut. Dies ähnelt der üblichen Vorgehensweise, bei einem Zeiger an der Vorderseite zu bleiben und einen Unterstrich vor globalen Variablen zu verwenden (dies ist etwas seltener). und die Variablennamen zu verwenden i, jund kfür temporäre Schleifenvariablen.

In Code, in dem Wortgröße und Reihenfolge wichtig sind, werden häufig benutzerdefinierte Typen verwendet, die explizit sind, z. B. BYTE WORD(normalerweise 16 Bit) DWORD(32 Bit).

int_tist nicht so gut, weil die Definition von intzwischen den Plattformen variiert - also wem intentsprechen Sie? (Obwohl heutzutage die meisten PC-zentrierten Entwicklungen es als 32 Bit behandeln, behandeln viele Dinge für die Nicht-PC-Entwicklung Ints immer noch als 16 Bit).

Spielzeugbauer
quelle
10

Es bedeutet Typ. size_tist der Größentyp.

Douglas Mayle
quelle
8

Es gab einige gute Erklärungen zu diesem Thema. Nur um einen weiteren Grund für die Neudefinition der Typen hinzuzufügen:

In vielen eingebetteten Projekten werden alle Typen neu definiert, um die angegebene Größe für die Typen korrekt anzugeben und die Portabilität zwischen verschiedenen Plattformen (dh Hardwaretyp-Compilern) zu verbessern.

Ein weiterer Grund besteht darin, Ihren Code auf verschiedene Betriebssysteme portierbar zu machen und Kollisionen mit vorhandenen Typen im Betriebssystem zu vermeiden, die Sie in Ihren Code integrieren. Hierzu wird normalerweise ein eindeutiges (möglichst) Präfix hinzugefügt.

Beispiel:

typedef unsigned long dc_uint32_t;
Ilya
quelle
7

Wenn Sie mit Hardware-Schnittstellencode arbeiten, hat der Autor des Codes, den Sie betrachten, möglicherweise int_teine bestimmte Ganzzahl definiert. Der C-Standard weist dem intTyp keine bestimmte Größe zu (dies hängt möglicherweise von Ihrem Compiler und Ihrer Zielplattform ab), und die Verwendung eines bestimmten int_tTyps würde dieses Portabilitätsproblem vermeiden.

Dies ist eine besonders wichtige Überlegung für den Code der Hardwareschnittstelle, weshalb Sie möglicherweise die Konvention dort zum ersten Mal bemerkt haben.

Greg Hewgill
quelle
1
Dies wird keine sehr gute Praxis sein, ich würde erwarten, dass man [u] int_ [32 16 8] _t definiert, um klar zu machen, welche Größe Sie definieren.
Ilya
1
Sie haben völlig Recht, "int_t" selbst sagt dem Programmierer, dass es sich um einen benutzerdefinierten Typ handelt, aber nicht um das, was er wirklich ist!
Greg Hewgill
0

Zum Beispiel 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 bedeutet immer definiert durch typedef.

Jayhello
quelle