Saya perhatikan bahwa kode C dan C ++ modern tampaknya menggunakan size_t
alih-alih int
/ unsigned int
cukup banyak di mana-mana - dari parameter untuk fungsi string C ke STL. Saya ingin tahu alasannya dan manfaatnya.
492
The size_t
tipe adalah tipe unsigned integer yang merupakan hasil dari sizeof
operator (dan offsetof
operator), sehingga dijamin akan cukup besar untuk menampung ukuran objek terbesar sistem Anda dapat menangani (misalnya, array statis 8Gb).
The size_t
Tipe mungkin lebih besar dari, sama dengan, atau lebih kecil dari unsigned int
, dan compiler Anda mungkin membuat asumsi tentang hal itu untuk optimasi.
Anda dapat menemukan informasi yang lebih tepat dalam standar C99, bagian 7.17, konsep yang tersedia di Internet dalam format pdf , atau dalam standar C11, bagian 7.19, juga tersedia sebagai konsep pdf .
size_t
dapat mewakili! Jika tidak, siapa yang mau?Classic C (dialek awal C yang dijelaskan oleh Brian Kernighan dan Dennis Ritchie dalam Bahasa Pemrograman C, Prentice-Hall, 1978) tidak menyediakan
size_t
. Komite standar C diperkenalkansize_t
untuk menghilangkan masalah portabilitasDijelaskan secara terperinci di embedded.com (dengan contoh yang sangat bagus)
sumber
Singkatnya,
size_t
tidak pernah negatif, dan ini memaksimalkan kinerja karena itu diketikkan akan menjadi tipe integer tak bertanda yang cukup besar - tetapi tidak terlalu besar - untuk mewakili ukuran objek terbesar yang mungkin ada pada platform target.Ukuran tidak boleh negatif, dan memang
size_t
merupakan tipe yang tidak ditandatangani. Selain itu, karenasize_t
tidak ditandatangani, Anda dapat menyimpan angka yang kira-kira dua kali lebih besar dari pada tipe bertanda tangan yang sesuai, karena kita dapat menggunakan bit tanda untuk mewakili besarnya, seperti semua bit lainnya dalam bilangan bulat yang tidak ditandai. Ketika kita memperoleh satu bit lagi, kita mengalikan rentang angka yang bisa kita wakili dengan faktor sekitar dua.Jadi, Anda bertanya, mengapa tidak menggunakan saja
unsigned int
? Mungkin tidak dapat menampung angka yang cukup besar. Dalam implementasi di manaunsigned int
32 bit, jumlah terbesar yang bisa diwakilinya adalah4294967295
. Beberapa prosesor, seperti IP16L32, dapat menyalin objek yang lebih besar dari4294967295
byte.Jadi, Anda bertanya, mengapa tidak menggunakan
unsigned long int
? Ini memerlukan tol kinerja pada beberapa platform. Standar C mensyaratkan bahwalong
menempati setidaknya 32 bit. Platform IP16L32 mengimplementasikan setiap 32-bit selama sepasang kata 16-bit. Hampir semua operator 32-bit pada platform ini memerlukan dua instruksi, jika tidak lebih, karena mereka bekerja dengan 32 bit dalam dua potongan 16-bit. Misalnya, memindahkan panjang 32-bit biasanya membutuhkan dua instruksi mesin - satu untuk memindahkan setiap potongan 16-bit.Menggunakan
size_t
menghindari tol kinerja ini. Menurut artikel yang fantastis ini , "Jenissize_t
adalah typedef yang merupakan alias untuk beberapa tipe integer yang tidak ditandatangani, biasanyaunsigned int
atauunsigned long
, tetapi bahkan mungkinunsigned long long
. Setiap implementasi Standar C seharusnya memilih integer yang tidak ditandai yang cukup besar - tetapi tidak lebih besar dari yang dibutuhkan - untuk mewakili ukuran objek terbesar yang mungkin ada di platform target. "sumber
unsigned int
kaleng dan bervariasi dari satu sistem ke sistem lainnya. Ini diperlukan untuk menjadi setidaknya65536
, tapi itu biasa4294967295
dan bisa menjadi18446744073709551615
(2 ** 64-1) pada beberapa sistem.unsigned char
). Standar ini tampaknya tidak mengandung string '65535' atau '65536' di mana saja, dan '+32767' hanya terjadi (1.9: 9) dalam catatan sebagai kemungkinan integer terbesar yang dapat diwakili dalamint
; tidak ada jaminan yang diberikan bahkan yangINT_MAX
tidak bisa lebih kecil dari itu!Tipe size_t adalah tipe yang dikembalikan oleh operator sizeof. Ini adalah integer tanpa tanda yang mampu mengekspresikan ukuran dalam byte dari berbagai memori yang didukung pada mesin host. Ini (biasanya) terkait dengan ptrdiff_t dalam ptrdiff_t adalah nilai integer yang ditandatangani sehingga sizeof (ptrdiff_t) dan sizeof (size_t) sama.
Saat menulis kode C Anda harus selalu menggunakan size_t setiap kali berurusan dengan rentang memori.
Tipe int di sisi lain pada dasarnya didefinisikan sebagai ukuran nilai integer (ditandatangani) yang dapat digunakan oleh mesin host untuk melakukan aritmatika integer paling efisien. Sebagai contoh, pada banyak komputer jenis PC yang lebih lama, sizeof nilai (size_t) akan menjadi 4 (byte) tetapi sizeof (int) akan menjadi 2 (byte). Aritmatika 16 bit lebih cepat daripada aritmatika 32 bit, meskipun CPU dapat menangani ruang memori (logis) hingga 4 GiB.
Gunakan tipe int hanya ketika Anda peduli efisiensi karena ketepatan sebenarnya sangat bergantung pada opsi kompiler dan arsitektur mesin. Secara khusus standar C menentukan invarian berikut: sizeof (char) <= sizeof (pendek) <= sizeof (int) <= sizeof (panjang) tidak menempatkan batasan lain pada representasi aktual dari presisi yang tersedia untuk programmer untuk masing-masing tipe primitif ini.
Catatan: Ini BUKAN sama dengan di Jawa (yang sebenarnya menentukan presisi bit untuk masing-masing tipe 'char', 'byte', 'short', 'int' dan 'long').
sumber
size_t
mampu mewakili ukuran objek tunggal (mis: angka, array, struktur). Seluruh rentang memori dapat melebihisize_t
size_t
- Saya harap Anda tidak bermaksud demikian. Sebagian besar waktu kita tidak berurusan dengan array di mana kardinalitas ruang alamat + portabilitas bahkan penting. Dalam kasus ini, Anda akan mengambilsize_t
. Dalam setiap kasus lain Anda mengambil indeks dari bilangan bulat (masuk). Karena kebingungan (yang datang tanpa peringatan) yang timbul dari perilaku arus bawah yang tidak terduga dari orang-orang yang tidak diundang lebih umum dan lebih buruk daripada masalah portabilitas yang mungkin timbul dalam kasus-kasus lain.Ketik size_t harus cukup besar untuk menyimpan ukuran objek apa pun yang mungkin. Int unsigned tidak harus memenuhi kondisi itu.
Misalnya dalam sistem 64 bit int dan unsigned int mungkin lebar 32 bit, tetapi size_t harus cukup besar untuk menyimpan angka lebih besar dari 4G
sumber
size_t
hanya harus sebesar itu jika kompiler dapat menerima tipe X sehingga sizeof (X) akan menghasilkan nilai yang lebih besar dari 4G. Sebagian besar penyusun akan menolak mistypedef unsigned char foo[1000000000000LL][1000000000000LL]
, dan bahkanfoo[65536][65536];
dapat ditolak secara sah jika melebihi batas yang ditentukan oleh implementasi yang terdokumentasi.Kutipan ini dari manual glibc 0.02 mungkin juga relevan ketika meneliti topik:
Ada potensi masalah dengan tipe size_t dan versi GCC sebelum rilis 2.4. ANSI C mengharuskan size_t selalu menjadi tipe yang tidak ditandai. Untuk kompatibilitas dengan file header sistem yang ada, GCC mendefinisikan size_t di
stddef.h' to be whatever type the system's
sys / types.h 'mendefinisikannya menjadi. Sebagian besar sistem Unix yang mendefinisikan size_t di `sys / types.h ', mendefinisikannya sebagai tipe yang ditandatangani. Beberapa kode di pustaka tergantung pada size_t menjadi tipe yang tidak ditandatangani, dan tidak akan berfungsi dengan benar jika ditandatangani.Kode pustaka GNU C yang mengharapkan size_t tidak ditandatangani adalah benar. Definisi size_t sebagai tipe yang ditandatangani salah. Kami berencana bahwa dalam versi 2.4, GCC akan selalu mendefinisikan size_t sebagai tipe yang tidak ditandatangani, dan
fixincludes' script will massage the system's
sys / types.h 'agar tidak bertentangan dengan ini.Sementara itu, kami mengatasi masalah ini dengan memberi tahu GCC secara eksplisit untuk menggunakan tipe yang tidak ditandatangani untuk size_t saat mengkompilasi pustaka GNU C. `configure 'akan secara otomatis mendeteksi tipe apa yang digunakan GCC untuk mengatur size_t untuk menimpanya jika perlu.
sumber
Jika kompiler saya disetel ke 32 bit,
size_t
tidak lain adalah typedef untukunsigned int
. Jika kompiler saya disetel ke 64 bit,size_t
tidak lain adalah typedef untukunsigned long long
.sumber
unsigned long
untuk kedua kasus pada beberapa OS.size_t adalah ukuran pointer.
Jadi dalam 32 bit atau model ILP32 (integer, panjang, pointer) umum size_t adalah 32 bit. dan dalam 64 bit atau model LP_t LP64 (panjang, pointer) umum adalah 64 bit (bilangan bulat masih 32 bit).
Ada beberapa model lain tetapi ini adalah model yang digunakan g ++ (setidaknya secara default)
sumber
size_t
belum tentu ukurannya sama dengan pointer, meskipun biasanya demikian. Pointer harus dapat menunjuk ke lokasi mana pun dalam memori;size_t
hanya harus cukup besar untuk mewakili ukuran objek tunggal terbesar.