Apa yang diwakili oleh tipe diikuti oleh _t (garis bawah-t)?

261

Ini sepertinya pertanyaan sederhana, tetapi saya tidak dapat menemukannya dengan pencarian Stack Overflow atau Google. Apa jenis diikuti oleh _tmean? Seperti

int_t anInt;

Saya melihatnya dalam kode C yang dimaksudkan untuk berhubungan erat dengan perangkat keras — saya tidak bisa tidak berpikir mereka terkait.

Kevin Griffin
sumber
3
Di mana int_tdidefinisikan? Jika selalu didefinisikan sebagai int, itu tidak berguna; itu jauh lebih jelas untuk digunakan intsecara langsung. Jika itu tidak selalu didefinisikan sebagai int(katakanlah, jika bisa long intatau short int), maka itu adalah nama yang dipilih dan membingungkan.
Keith Thompson

Jawaban:

213

Seperti yang dicatat oleh Douglas Mayle, ini pada dasarnya menunjukkan nama tipe. Akibatnya, Anda akan keliru untuk mengakhiri nama variabel atau fungsi dengan ' _t' karena dapat menyebabkan kebingungan. Serta size_t, yang mendefinisikan standar C89 wchar_t, off_t, ptrdiff_t, dan mungkin beberapa orang lain aku sudah lupa. The C99 standar mendefinisikan banyak jenis tambahan, seperti uintptr_t, intmax_t, int8_t, uint_least16_t, uint_fast32_t, dan sebagainya. Tipe-tipe baru ini secara formal didefinisikan <stdint.h>tetapi paling sering Anda akan menggunakan <inttypes.h>yang (tidak biasa untuk header C standar) termasuk <stdint.h>. Ini ( <inttypes.h>) juga mendefinisikan makro untuk digunakan dengan printf()dan scanf().

Seperti yang dicatat oleh Matt Curtis, tidak ada arti penting bagi kompiler dalam sufiks; itu adalah konvensi yang berorientasi pada manusia.

Namun, Anda juga harus mencatat bahwa POSIX mendefinisikan banyak nama tipe tambahan yang diakhiri dengan ' _t', dan menyimpan akhiran untuk implementasi. Itu berarti bahwa jika Anda bekerja pada sistem yang berhubungan dengan POSIX, mendefinisikan nama tipe Anda sendiri dengan konvensi tidak disarankan. Sistem yang saya kerjakan telah melakukannya (lebih dari 20 tahun); kami secara teratur tersandung oleh sistem yang mendefinisikan tipe dengan nama yang sama seperti yang kami definisikan.

Jonathan Leffler
sumber
4
tampaknya masuk akal bahwa OS dan pustaka runtime umum mendefinisikan tipe dengan nama generik; tetapi bukankah tipe perusahaan Anda juga harus diawali dengan awalan atau semacamnya?
Toybuilder
17
Saya menggunakan _type alih-alih _t pada typedefs saya untuk menghindari hal itu.
CesarB
4
@ Jonathan Leffler - Konvensi penamaan apa yang akan Anda gunakan untuk tipe yang ditentukan pengguna?
J. Andrew Laughlin
15
@Andrew: jika Anda memiliki singkatan yang nyaman untuk digunakan sebagai awalan, maka Anda mungkin aman menggunakan abbr_xxxxx_tnama jenis. Tanpa awalan seperti itu, Anda bisa ketahuan kapan saja. Secara umum, _ttipe standar menggunakan semua huruf kecil ( FILEdan DIRdua pengecualian, dua kali - semua tutup, dan tidak _t), sehingga Anda dapat menggunakan CamelCase_tdengan keamanan sedang, dengan atau tanpa tutup depan. Sistem tempat saya bekerja cenderung hidup berbahaya dan menggunakannya _t, tetapi kadang-kadang mengganggu kita. Saya cenderung menggunakan CamelCasetanpa akhiran untuk pekerjaan saya sendiri; fungsi saya biasanya semua huruf kecil.
Jonathan Leffler
5
@ JonathanLeffler, saya sudah mulai menggunakan konvensi itu, CamelCase untuk jenis, huruf kecil untuk fungsi. Saya mencari pertanyaan ini dengan harapan saya bukan satu-satunya. Terima kasih atas validasinya!
Austin Mullins
50

Ini adalah konvensi yang digunakan untuk memberi nama tipe data, misalnya dengan typedef:


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

mmacaulay
sumber
43

The _tbiasanya membungkus sebuah definisi jenis buram.

GCC hanya menambahkan nama yang diakhiri dengan _tnamespace cadangan yang tidak boleh Anda gunakan, untuk menghindari konflik dengan versi Standar C dan POSIX yang akan datang (manual pustaka GNU C) . Setelah beberapa penelitian, saya akhirnya menemukan referensi yang benar di dalam Standar POSIX (1003.1, Rationale (Informative)):

B.2.12 Jenis Data

Persyaratan bahwa tipe tambahan yang didefinisikan dalam bagian ini diakhiri dengan '' _t '' didorong oleh masalah polusi ruang nama. Sulit untuk menentukan jenis (di mana jenis itu bukan yang didefinisikan oleh IEEE Std 1003.1-2001) dalam satu file header dan menggunakannya dalam file lain tanpa menambahkan simbol ke ruang nama program. Untuk memungkinkan pelaksana menyediakan jenis mereka sendiri, semua aplikasi yang sesuai diperlukan untuk menghindari simbol yang diakhiri dengan '' _t '', yang memungkinkan pelaksana menyediakan jenis tambahan. Karena penggunaan utama tipe adalah dalam definisi anggota struktur, yang dapat (dan dalam banyak kasus harus) ditambahkan ke struktur yang didefinisikan dalam IEEE Std 1003.1-2001, kebutuhan akan tipe tambahan menarik.

Singkatnya, Standar mengatakan bahwa ada peluang bagus untuk memperpanjang daftar tipe Standar, oleh karena itu Standar membatasi _truang nama untuk penggunaannya sendiri.

Misalnya, program Anda cocok dengan POSIX 1003.1 Masalah 6 dan Anda menentukan jenisnya foo_t. POSIX 1003.1 Masalah 7 akhirnya dirilis dengan tipe yang baru didefinisikan foo_t. Program Anda tidak cocok dengan versi baru, yang mungkin menjadi masalah. Membatasi _tpenggunaan mencegah dari refactoring kode. Dengan demikian, jika Anda bertujuan untuk kepatuhan POSIX, Anda harus menghindari standar _tsebagaimana dinyatakan olehnya.

Catatan: secara pribadi, saya mencoba untuk tetap pada POSIX karena saya pikir itu memberikan dasar-dasar yang baik untuk pemrograman bersih. Terlebih lagi, saya cukup menyukai panduan Linux Coding Style (bab 5) . Ada beberapa alasan bagus mengapa tidak menggunakan typedef. Semoga bantuan ini!

Benoit
sumber
18

Ini adalah konvensi penamaan standar untuk tipe data, biasanya ditentukan oleh typedefs. Banyak kode C yang berhubungan dengan register perangkat keras menggunakan nama standar yang ditentukan C99 untuk tipe data ukuran tetap yang ditandatangani dan tidak ditandatangani. Sebagai konvensi, nama-nama ini dalam file header standar (stdint.h), dan diakhiri dengan _t.

mkClark
sumber
11

Itu hanya konvensi yang berarti "mengetik". Itu berarti tidak ada yang istimewa bagi kompiler.

Matt Curtis
sumber
11

Secara _tinheren tidak memiliki makna khusus. Tapi itu sudah umum digunakan untuk menambahkan _takhiran ke typedef.

Anda mungkin lebih terbiasa dengan praktik C yang umum untuk penamaan variabel ... Ini mirip dengan bagaimana biasa menempel ap di depan untuk penunjuk, dan menggunakan garis bawah di depan variabel global (ini agak kurang umum) , dan menggunakan nama variabel i, jdan kuntuk variabel lingkaran sementara.

Dalam kode di mana ukuran kata dan pemesanan penting, sangat umum untuk menggunakan jenis yang ditentukan khusus yang eksplisit, seperti BYTE WORD(biasanya 16-bit) DWORD(32-bit).

int_ttidak begitu baik, karena definisi intbervariasi di antara platform - jadi siapa intyang Anda sesuaikan? (Meskipun, saat ini, sebagian besar pengembangan PC-sentris memperlakukannya sebagai 32 bit, banyak hal untuk pengembangan non-PC masih memperlakukan int sebagai 16 bit).

Toybuilder
sumber
10

Itu artinya tipe. size_tadalah tipe ukuran.

Douglas Mayle
sumber
8

Ada beberapa penjelasan bagus tentang masalah ini. Hanya untuk menambahkan alasan lain untuk mendefinisikan kembali jenis:

Dalam banyak proyek tertanam, semua jenis didefinisikan ulang untuk dengan benar menyatakan ukuran yang diberikan untuk jenis dan untuk meningkatkan portabilitas di berbagai platform (yaitu kompiler jenis perangkat keras).

Alasan lain adalah untuk membuat kode Anda portabel di berbagai OS dan untuk menghindari tabrakan dengan tipe yang ada di OS yang Anda integrasikan dalam kode Anda. Untuk ini, biasanya awalan yang unik (mungkin) ditambahkan.

Contoh:

typedef unsigned long dc_uint32_t;
Ilya
sumber
7

Jika Anda berurusan dengan kode antarmuka perangkat keras, pembuat kode yang Anda lihat mungkin telah didefinisikan int_tsebagai bilangan bulat ukuran tertentu. Standar C tidak menetapkan ukuran spesifik untuk inttipe (itu tergantung pada kompiler dan platform target Anda, berpotensi), dan menggunakan int_ttipe spesifik akan menghindari masalah portabilitas.

Ini adalah pertimbangan yang sangat penting untuk kode antarmuka perangkat keras, yang mungkin mengapa Anda pertama kali memperhatikan konvensi di sana.

Greg Hewgill
sumber
1
ini bukan praktik yang sangat baik, saya akan mengharapkan seseorang untuk mendefinisikan [u] int_ [32 16 8] _t untuk memperjelas apa ukuran yang Anda tetapkan.
Ilya
1
Anda benar, "int_t" dengan sendirinya memberitahu programmer bahwa itu adalah tipe yang ditentukan pengguna tetapi tidak seperti apa sebenarnya!
Greg Hewgill
0

Misalnya di 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 selalu berarti didefinisikan oleh typedef.

Jayhello
sumber