Dalam beberapa contoh C ++ saya melihat penggunaan tipe di size_t
mana saya akan menggunakan yang sederhana int
. Apa bedanya, dan mengapa size_t
harus lebih baik?
Dalam beberapa contoh C ++ saya melihat penggunaan tipe di size_t
mana saya akan menggunakan yang sederhana int
. Apa bedanya, dan mengapa size_t
harus lebih baik?
Jawaban:
Dari Wikipedia yang ramah :
File header stdlib.h dan stddef.h menentukan tipe data yang disebut size_t yang digunakan untuk mewakili ukuran objek. Fungsi pustaka yang mengambil ukuran mengharapkannya dari tipe size_t, dan sizeof operator mengevaluasi ke size_t.
Jenis sebenarnya dari size_t tergantung pada platform; kesalahan umum adalah menganggap size_t sama dengan unsigned int, yang dapat menyebabkan kesalahan pemrograman, terutama karena arsitektur 64-bit menjadi lebih umum.
Juga, periksa Mengapa size_t penting
/usr/include/stdlib.h
mendapatkan definisi dari /usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.h
dan di dalamnya default untuk long unsigned int
kecuali beberapa file header lainnya mengatakan sebaliknya.
size_t adalah tipe yang digunakan untuk merepresentasikan ukuran (sesuai namanya). Platformnya (dan bahkan berpotensi implementasi) bergantung, dan harus digunakan hanya untuk tujuan ini. Jelas, mewakili ukuran, size_t tidak ditandatangani. Banyak fungsi stdlib, termasuk malloc, sizeof dan berbagai fungsi operasi string menggunakan size_t sebagai datatype.
Int ditandatangani secara default, dan meskipun ukurannya juga tergantung platform, itu akan menjadi 32bits tetap pada kebanyakan mesin modern (dan meskipun size_t 64 bit pada arsitektur 64-bit, int tetap 32bit lama pada arsitektur tersebut).
Untuk meringkas: gunakan size_t untuk mewakili ukuran objek dan int (atau panjang) dalam kasus lain.
The size_t
jenis didefinisikan sebagai jenis terpisahkan unsigned dari sizeof
operator. Di dunia nyata, Anda akan sering melihat int
didefinisikan sebagai 32 bit (untuk kompatibilitas mundur) tetapi size_t
didefinisikan sebagai 64 bit (sehingga Anda dapat mendeklarasikan array dan struktur lebih dari 4 GiB dalam ukuran) pada platform 64-bit. Jika a long int
juga 64-bit, ini disebut konvensi LP64; jikalong int
32 bit tetapi long long int
dan pointer 64 bit, itu LLP64. Anda juga mungkin mendapatkan kebalikannya, sebuah program yang menggunakan instruksi 64-bit untuk kecepatan, tetapi pointer 32-bit untuk menghemat memori. Juga, int
ditandatangani dan size_t
tidak ditandatangani.
Secara historis ada sejumlah platform lain di mana alamat lebih luas atau lebih pendek dari ukuran asli int
. Pada kenyataannya, di tahun 70-an dan awal 80-an, ini lebih umum daripada tidak: semua mikrokomputer 8-bit yang populer memiliki register 8-bit dan alamat 16-bit, dan transisi antara 16 dan 32 bit juga menghasilkan banyak mesin yang memiliki alamat yang lebih luas daripada register mereka. Saya kadang-kadang masih melihat pertanyaan di sini tentang Borland Turbo C untuk MS-DOS, yang mode memori Huge memiliki 20-bit alamat disimpan dalam 32 bit pada CPU 16-bit (tetapi yang dapat mendukung set instruksi 32-bit dari 80386); Motorola 68000 memiliki ALU 16-bit dengan register dan alamat 32-bit; ada mainframe IBM dengan alamat 15-bit, 24-bit atau 31-bit. Anda juga masih melihat berbagai ukuran ALU dan address-bus dalam sistem embedded.
Setiap saat int
lebih kecil dari size_t
, dan Anda mencoba untuk menyimpan ukuran atau offset dari file atau objek yang sangat besar dalam suatu unsigned int
, ada kemungkinan itu bisa meluap dan menyebabkan bug. Dengan int
, ada juga kemungkinan mendapatkan angka negatif. Jika suatu int
atauunsigned int
lebih lebar, program akan berjalan dengan benar tetapi membuang-buang memori.
Anda biasanya harus menggunakan tipe yang benar untuk tujuan tersebut jika Anda menginginkan portabilitas. Banyak orang akan merekomendasikan agar Anda menggunakan matematika yang ditandatangani alih-alih tidak ditandatangani (untuk menghindari bug yang jahat dan halus 1U < -3
). Untuk tujuan itu, mendefinisikan perpustakaan standar ptrdiff_t
di <stddef.h>
sebagai jenis ditandatangani hasil mengurangkan pointer dari yang lain.
Yang mengatakan, solusi mungkin untuk batas-memeriksa semua alamat dan penyeimbang terhadap INT_MAX
dan salah satu 0
atau yang INT_MIN
sesuai, dan nyalakan peringatan kompiler tentang membandingkan jumlah yang ditandatangani dan tidak ditandatangani jika Anda kehilangan. Anda harus selalu, selalu, selalu memeriksa akses array Anda untuk limpahan dalam C.
Itu karena size_t bisa berupa apa saja selain int (mungkin struct). Idenya adalah bahwa itu memisahkan pekerjaan itu dari tipe yang mendasarinya.
size_t
ditetapkan sebagai tipe integer yang tidak ditandatangani . C11 §6.5.3.4 5 "Nilai hasil dari kedua operator ( sizeof
_Alignof
) adalah yang ditentukan implementasi, dan tipenya (tipe integer yang tidak ditandatangani) adalah size_t
,".
Definisi SIZE_T
ini ditemukan di:
https://msdn.microsoft.com/en-us/library/cc441980.aspx dan https://msdn.microsoft.com/en-us/library/cc230394.aspx
Menempel di sini informasi yang diperlukan:
SIZE_T
adalah ULONG_PTR
jumlah maksimum byte yang dapat ditunjukkan oleh sebuah pointer.
Jenis ini dinyatakan sebagai berikut:
typedef ULONG_PTR SIZE_T;
SEBUAH ULONG_PTR
adalah tipe panjang tanpa tanda yang digunakan untuk presisi pointer. Ini digunakan ketika casting pointer ke tipe panjang untuk melakukan aritmatika pointer.
Jenis ini dinyatakan sebagai berikut:
typedef unsigned __int3264 ULONG_PTR;
SIZE_T
bukan size_t
, apa yang ditanyakan OP.
SIZE_T
sama sekali berbeda dari size_t
. Anda tidak dapat mendeklarasikan variabel tipe SIZE_T
.