Cosa rappresenta un tipo seguito da _t (underscore-t)?

Sembra una domanda semplice, ma non riesco a trovarla con la ricerca Stack Overflow o Google. Cosa significa un tipo seguito da un significato? Ad esempio

 int_t anInt; 

Lo vedo molto nel codice C pensato per trattare da vicino l’hardware, non posso fare a meno di pensare che siano correlati.

Come ha notato Douglas Mayle, in pratica indica un nome di tipo. Di conseguenza, sarebbe sconsigliato terminare nomi di variabili o di funzioni con ” _t ” poiché potrebbe causare una certa confusione. Oltre a size_t , lo standard C89 definisce wchar_t , off_t , ptrdiff_t e probabilmente alcuni altri che ho dimenticato. Lo standard C99 definisce molti tipi extra, come uintptr_t , intmax_t , int8_t , uint_least16_t , uint_fast32_t e così via. Questi nuovi tipi sono definiti formalmente in ma molto spesso userete che (in modo insolito per le intestazioni C standard) include . It ( ) definisce anche le macro da usare con printf() e scanf() .

Come ha notato Matt Curtis, non c’è alcun significato per il compilatore nel suffisso; è una convenzione orientata all’uomo.

Tuttavia, dovresti anche notare che POSIX definisce molti altri nomi di tipi che terminano con ‘ _t ‘ e riserva il suffisso per l’implementazione. Ciò significa che se stai lavorando su sistemi POSIX, la definizione dei tuoi nomi di tipo con la convenzione è sconsiderata. Il sistema su cui lavoro lo ha fatto (per più di 20 anni); veniamo regolarmente inciampati dai sistemi che definiscono i tipi con lo stesso nome che definiamo.

È una convenzione utilizzata per denominare i tipi di dati, ad esempio con typedef :

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

In genere, di solito include una definizione di tipo opaco.

GCC aggiunge semplicemente nomi che terminano con _t allo spazio dei nomi riservato che non è ansible utilizzare, per evitare conflitti con versioni future di Standard C e POSIX (manuale della libreria GNU C) . Dopo alcune ricerche, ho finalmente trovato il riferimento corretto all’interno dello standard POSIX (1003.1, Razionale (informativo)):

B.2.12 Tipi di dati

Il requisito che i tipi aggiuntivi definiti in questa sezione terminano con ” _t ” è stato richiesto dal problema dell’inquinamento dello spazio dei nomi. È difficile definire un tipo (in cui quel tipo non è definito da IEEE Std 1003.1-2001) in un file di intestazione e utilizzarlo in un altro senza aggiungere simboli allo spazio dei nomi del programma. Per consentire agli implementatori di fornire i propri tipi, sono richieste tutte le applicazioni conformi per evitare che i simboli terminino con ” _t ”, che consente all’implementatore di fornire tipi aggiuntivi. Poiché un uso importante dei tipi è nella definizione dei membri della struttura, che può (e in molti casi deve) essere aggiunto alle strutture definite nello standard IEEE 1003.1-2001, la necessità di tipi aggiuntivi è convincente.

In poche parole, lo standard dice che ci sono buone probabilità di estendere l’elenco dei tipi standard, quindi lo standard limita lo spazio dei nomi _t per il proprio uso.

Ad esempio, il tuo programma corrisponde a POSIX 1003.1 Issues 6 e hai definito un tipo foo_t . POSIX 1003.1 Issues 7 è finalmente rilasciato con un nuovo tipo definito foo_t . Il tuo programma non corrisponde alla nuova versione, il che potrebbe essere un problema. Limitare l’uso di _t impedisce di refactoring del codice. Quindi, se si mira ad una conformità POSIX, si dovrebbe assolutamente evitare il _t come lo afferma lo standard.

Nota a margine: personalmente, cerco di attenermi a POSIX perché ritengo che dia buone basi per una programmazione pulita. Inoltre, mi piacciono molto le linee guida di Linux Coding Style (capitolo 5) . Ci sono alcune buone ragioni per le quali non si usa typedef. Spero che questo aiuto!

È una convenzione di denominazione standard per tipi di dati, generalmente definita da typedef. Un sacco di codice C che si occupa di registri hardware utilizza nomi standard definiti da C99 per i tipi di dati a dimensione fissa firmati e non firmati. Come convenzione, questi nomi si trovano in un file di intestazione standard (stdint.h) e terminano con _t.

Il _t non ha intrinsecamente alcun significato speciale. Ma è diventato di uso comune aggiungere il suffisso _t a typedef’s.

Potresti avere più familiarità con le pratiche C comuni per la denominazione delle variabili … Questo è simile al modo in cui è comune attaccare l’ap in primo piano per un puntatore e usare un trattino di sottolineatura davanti alle variabili globali (questo è un po ‘meno comune) e per utilizzare i nomi delle variabili i , j e k per le variabili di ciclo temporanee.

Nel codice in cui la dimensione e l’ordine delle parole sono importanti, è molto comune utilizzare tipi definiti personalizzati che sono espliciti, come DWORD BYTE WORD (normalmente a 16 bit) (32 bit).

int_t non è così buono, perché la definizione di int varia tra piattaforms – quindi a chi int si adegua? (Anche se, al giorno d’oggi, la maggior parte dello sviluppo incentrato sul PC lo considera come 32 bit, molte cose per lo sviluppo non-PC trattano ancora int come 16 bit).

Significa tipo. size_t è il tipo di dimensione.

È solo una convenzione che significa “tipo”. Significa niente di speciale per il compilatore.

Se hai a che fare con il codice dell’interfaccia hardware, l’autore del codice che stai guardando potrebbe aver definito int_t un numero intero di dimensioni specifiche. Lo standard C non assegna una dimensione specifica al tipo int (dipende potenzialmente dal compilatore e dalla piattaforma di destinazione, potenzialmente) e l’utilizzo di un tipo int_t specifico eviterebbe quel problema di portabilità.

Questa è una considerazione particolarmente importante per il codice dell’interfaccia hardware, che potrebbe essere il motivo per cui prima hai notato la convenzione.

C’erano alcune buone spiegazioni sull’argomento. Solo per aggiungere un altro motivo per ridefinire i tipi:

In molti progetti incorporati, tutti i tipi vengono ridefiniti per indicare correttamente il tipo di dimensionamento ai tipi e per migliorare la portabilità tra piattaforms diverse (ad esempio compilatori di tipi di hardware).

Un altro motivo sarà rendere portatile il codice tra diversi sistemi operativi ed evitare collisioni con tipi esistenti nel sistema operativo che si sta integrando nel codice. Per questo, in genere viene aggiunto un prefisso univoco (come ansible).

Esempio:

 typedef unsigned long dc_uint32_t; 

Ad esempio 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 sempre significa definito da typedef.