Dalam beberapa contoh C ++ saya melihat penggunaan tipe di size_tmana saya akan menggunakan yang sederhana int. Apa bedanya, dan mengapa size_tharus lebih baik?
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.
@NDEthos Tergantung! Pada ini di sini Linux /usr/include/stdlib.hmendapatkan definisi dari /usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.hdan di dalamnya default untuk long unsigned intkecuali beberapa file header lainnya mengatakan sebaliknya.
David Tonhofer
1
Saya mengkonfirmasi size_t ke tuncation berbahaya . Ini mungkin di luar topik, tetapi bagaimana menulis tambalan sendiri untuk memperbaiki kesalahan semacam itu ketika muncul ribuan kali di kernel linux?
user2284570
36
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_tjenis didefinisikan sebagai jenis terpisahkan unsigned dari sizeofoperator. Di dunia nyata, Anda akan sering melihat intdidefinisikan sebagai 32 bit (untuk kompatibilitas mundur) tetapi size_tdidefinisikan sebagai 64 bit (sehingga Anda dapat mendeklarasikan array dan struktur lebih dari 4 GiB dalam ukuran) pada platform 64-bit. Jika a long intjuga 64-bit, ini disebut konvensi LP64; jikalong int 32 bit tetapi long long intdan 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, intditandatangani dan size_ttidak 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 intlebih 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 intatauunsigned 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_tdi <stddef.h>sebagai jenis ditandatangani hasil mengurangkan pointer dari yang lain.
Yang mengatakan, solusi mungkin untuk batas-memeriksa semua alamat dan penyeimbang terhadap INT_MAXdan salah satu 0atau yang INT_MINsesuai, 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.
Saya pikir size_t sebenarnya dijamin menjadi alias untuk integer yang tidak ditandatangani, jadi tidak bisa menjadi struktur. Saya tidak memiliki referensi yang berguna untuk mendukung ini sekarang.
bersantai
9
@unwind: C99: TC3, 7.17 §2
Christoph
1
@danio Kenapa begitu? bisakah Anda menjelaskan?
Rüppell's Hering
2
Saya tidak akan menautkan ke cplusplus jika saya adalah Anda! Jika Anda tidak dapat mengutip pasal, ayat, paragraf dan kalimat maka itu semua hanya desas-desus! :-)
graham.reeds
1
size_tditetapkan 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,".
SIZE_Tadalah ULONG_PTRjumlah 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.
Jawaban:
Dari Wikipedia yang ramah :
Juga, periksa Mengapa size_t penting
sumber
/usr/include/stdlib.h
mendapatkan definisi dari/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.h
dan di dalamnya default untuklong 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.
sumber
The
size_t
jenis didefinisikan sebagai jenis terpisahkan unsigned darisizeof
operator. Di dunia nyata, Anda akan sering melihatint
didefinisikan sebagai 32 bit (untuk kompatibilitas mundur) tetapisize_t
didefinisikan sebagai 64 bit (sehingga Anda dapat mendeklarasikan array dan struktur lebih dari 4 GiB dalam ukuran) pada platform 64-bit. Jika along int
juga 64-bit, ini disebut konvensi LP64; jikalong int
32 bit tetapilong 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 dansize_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 darisize_t
, dan Anda mencoba untuk menyimpan ukuran atau offset dari file atau objek yang sangat besar dalam suatuunsigned int
, ada kemungkinan itu bisa meluap dan menyebabkan bug. Denganint
, ada juga kemungkinan mendapatkan angka negatif. Jika suatuint
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 standarptrdiff_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 satu0
atau yangINT_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.sumber
Itu karena size_t bisa berupa apa saja selain int (mungkin struct). Idenya adalah bahwa itu memisahkan pekerjaan itu dari tipe yang mendasarinya.
sumber
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) adalahsize_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.aspxMenempel di sini informasi yang diperlukan:
SIZE_T
adalahULONG_PTR
jumlah maksimum byte yang dapat ditunjukkan oleh sebuah pointer.Jenis ini dinyatakan sebagai berikut:
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:
sumber
SIZE_T
bukansize_t
, apa yang ditanyakan OP.SIZE_T
sama sekali berbeda darisize_t
. Anda tidak dapat mendeklarasikan variabel tipeSIZE_T
.