Jika itu adalah satu-satunya pilihan Anda, gunakan intjika some_sizeditandatangani, size_tjika tidak ditandatangani.
Nate
8
@Nate Itu tidak benar. POSIX memiliki tipe ssize_t tetapi tipe sebenarnya yang benar untuk digunakan adalah ptrdiff_t.
Steven Stewart-Gallus
2
Jawabannya tidak sejelas dalam Pemrograman Tingkat Rendah: C, Assembly, dan Eksekusi Program pada Intel® 64 . Seperti yang dinyatakan dalam buku ini, menggunakan indeks int imungkin tidak cukup untuk mengatasi array besar. Jadi dengan menggunakan size_t iAnda dapat mengatasi lebih banyak indeks, bahkan jika Anda memiliki array besar yang seharusnya tidak menjadi masalah. size_tadalah tipe data: biasanya a unsigned long inttetapi ini tergantung pada sistem Anda.
Menurut standar ISO C 1999 (C99), 1999 size_tadalah tipe integer yang tidak ditandai setidaknya 16 bit (lihat bagian 7.17 dan 7.18.3).
size_tadalah tipe data yang tidak ditandatangani yang didefinisikan oleh beberapa standar C / C ++, misalnya standar C99 ISO / IEC 9899, yang didefinisikan dalam stddef.h. 1 Dapat diimpor lebih lanjut dengan memasukkan
stdlib.hfile ini termasuk sub internal stddef.h.
Tipe ini digunakan untuk merepresentasikan ukuran suatu objek. Fungsi pustaka yang mengambil atau mengembalikan ukuran mengharapkannya bertipe atau memiliki tipe pengembalian size_t. Lebih lanjut, ukuran operator berbasis compiler yang paling sering digunakan harus dievaluasi dengan nilai konstan yang kompatibel dengannya
size_t.
Implikasinya, size_tadalah jenis yang dijamin untuk menyimpan indeks array apa pun.
"Fungsi perpustakaan yang mengambil atau mengembalikan ukuran mengharapkannya bertipe ... size_t" Kecuali stat itu () menggunakan off_t untuk ukuran file
Draemon
64
@Raemon Komentar itu mencerminkan kebingungan mendasar. size_tadalah untuk objek dalam memori. Standar C bahkan tidak mendefinisikan stat()atau off_t(itu adalah definisi POSIX) atau ada hubungannya dengan disk atau sistem file - berhenti sendiri di FILEstream. Manajemen memori virtual benar-benar berbeda dari sistem file dan manajemen file sejauh persyaratan ukuran berjalan, sehingga menyebutkan off_ttidak relevan di sini.
jw013
3
@ jw013: Saya jarang menyebutnya kebingungan mendasar, tetapi Anda membuat poin yang menarik. Namun, teks yang dikutip tidak mengatakan "ukuran objek dalam memori", dan "offset" hampir bukan nama yang baik untuk jenis ukuran terlepas dari tempat penyimpanannya.
Draemon
30
@Raemon Poin bagus. Jawaban ini mengutip Wikipedia, yang dalam hal ini tidak memiliki penjelasan terbaik, menurut pendapat saya. Standar C itu sendiri jauh lebih jelas: itu mendefinisikan size_tsebagai jenis hasil dari sizeofoperator (tentang 7.17p2 <stddef.h>). Bagian 6.5 menjelaskan dengan tepat bagaimana ekspresi C bekerja (6.5.3.4 untuk sizeof). Karena Anda tidak dapat menerapkan sizeofke file disk (kebanyakan karena C bahkan tidak menentukan cara kerja disk dan file), tidak ada ruang untuk kebingungan. Dengan kata lain, salahkan Wikipedia (dan jawaban ini untuk mengutip Wikipedia dan bukan standar C aktual).
jw013
2
@Raemon - Saya juga setuju dengan penilaian "kebingungan mendasar". Jika Anda belum membaca standar C / C ++, Anda mungkin berpikir "objek" mengacu pada "pemrograman berorientasi objek," yang tidak. Baca standar C, yang tidak memiliki objek OOP tersebut, tetapi belum memiliki objek, dan cari tahu. Jawabannya mungkin mengejutkan Anda!
Heath Hunnicutt
220
size_tadalah tipe yang tidak ditandatangani. Jadi, itu tidak dapat mewakili nilai negatif apa pun (<0). Anda menggunakannya saat menghitung sesuatu, dan yakin itu tidak negatif. Misalnya, strlen()mengembalikan a size_tkarena panjang string harus minimal 0.
Dalam contoh Anda, jika indeks loop Anda akan selalu lebih besar dari 0, mungkin masuk akal untuk digunakan size_t, atau tipe data yang tidak ditandatangani lainnya.
Ketika Anda menggunakan size_tobjek, Anda harus memastikan bahwa dalam semua konteks itu digunakan, termasuk aritmatika, Anda menginginkan nilai-nilai non-negatif. Sebagai contoh, katakanlah Anda memiliki:
dan Anda ingin menemukan perbedaan panjang str2dan str1. Anda tidak dapat melakukan:
int diff = s2 - s1;/* bad */
Ini karena nilai yang ditetapkan untuk diffselalu akan menjadi angka positif, bahkan ketika s2 < s1, karena perhitungan dilakukan dengan tipe yang tidak ditandatangani. Dalam hal ini, tergantung pada apa use case Anda, Anda mungkin lebih baik menggunakan int(atau long long) untuk s1dan s2.
Ada beberapa fungsi dalam C / POSIX yang bisa / harus digunakan size_t, tetapi tidak karena alasan historis. Sebagai contoh, parameter kedua fgetsseharusnya idealnya size_t, tetapi adalah int.
@Lok: Dua pertanyaan: 1) berapa ukuran size_t? 2) mengapa saya lebih suka size_tdaripada sesuatu seperti unsigned int?
Lazer
2
@Lazer: ukuran size_tyaitu sizeof(size_t). Standar C menjamin SIZE_MAXpaling tidak 65535. size_tadalah jenis yang dikembalikan oleh sizeofoperator, dan digunakan di perpustakaan standar (misalnya strlenpengembalian size_t). Seperti yang dikatakan Brendan, size_ttidak harus sama dengan unsigned int.
Alok Singhal
4
@ Lazer - ya, size_tdijamin menjadi tipe yang tidak ditandatangani.
Alok Singhal
2
@Celeritas tidak, maksud saya jenis yang tidak ditandatangani hanya dapat mewakili nilai-nilai non-negatif. Saya mungkin seharusnya mengatakan "Itu tidak bisa mewakili nilai negatif".
Alok Singhal
4
@JasonOster, komplemen dua bukanlah persyaratan dalam standar C. Jika nilai s2 - s1overflow int, perilaku tidak terdefinisi.
Alok Singhal
73
size_t adalah tipe yang bisa menampung indeks array apa pun.
Bergantung pada implementasinya, dapat berupa:
unsigned char
unsigned short
unsigned int
unsigned long
unsigned long long
Inilah cara size_tdidefinisikan di stddef.hmesin saya:
Tentunya typedef unsigned long size_ttergantung pada kompiler. Atau apakah Anda menyarankan agar selalu demikian?
chux - Reinstate Monica
4
@ chux: Memang, hanya karena satu implementasi mendefinisikannya seperti itu tidak berarti semua melakukannya. Contoh kasus: Windows 64-bit. unsigned longadalah 32-bit, size_tadalah 64-bit.
Tim Čas
2
apa tujuan size_t tepatnya? Ketika saya bisa membuat variabel untuk diri saya sendiri seperti: "int mysize_t;" atau "long mysize_t" atau "unsigned long mysize_t". Mengapa seseorang harus membuat variabel ini untuk saya?
midkin
1
@midkin size_tbukan variabel. Ini adalah tipe yang dapat Anda gunakan saat Anda ingin merepresentasikan ukuran objek dalam memori.
Arjun Sreedharan
1
apakah benar bahwa size_tselalu 32bits pada mesin 32-bit, 64bits juga?
Saya memiliki lingkungan yang sama, namun, saya telah mengujinya untuk 32 bit, melewati opsi "-m32" GCC, hasilnya adalah: "typedef unsigned int size_t". Terima kasih telah berbagi perintah yang luar biasa ini, Cirra, sangat membantu saya! :-)
silvioprog
2
Masalahnya sendiri tidak membingungkan. Pikiran yang membingungkanlah yang mencoba mengajukan banyak pertanyaan, dan memberikan banyak jawaban. Saya terkejut bahwa jawaban ini dan jawaban Arjun Sreedharan masih tidak menghentikan orang untuk bertanya dan menjawab.
biocyberman
1
Jawaban yang bagus, karena itu benar-benar memberitahu Anda apa yang size_tada , setidaknya pada distro Linux yang populer.
Karena belum ada yang menyebutkannya, makna linguistik utama size_tadalah bahwa sizeofoperator mengembalikan nilai jenis itu. Demikian juga, signifikansi utama dari ptrdiff_tpengurangan satu pointer dari yang lain akan menghasilkan nilai dari jenis itu. Fungsi pustaka yang menerimanya melakukannya karena itu akan memungkinkan fungsi tersebut untuk bekerja dengan objek yang ukurannya melebihi UINT_MAX pada sistem di mana objek tersebut dapat ada, tanpa memaksa penelepon membuang kode yang melewati nilai yang lebih besar dari "unsigned int" pada sistem di mana tipe yang lebih besar akan cukup untuk semua objek yang mungkin.
Pertanyaan saya selalu: Jika sizeof tidak pernah ada, apakah akan ada kebutuhan untuk size_t?
Dean P
@DeanP: Mungkin tidak, meskipun kemudian akan ada pertanyaan tentang jenis argumen apa yang harus digunakan untuk hal-hal seperti malloc(). Secara pribadi, saya ingin melihat versi yang mengambil argumen tipe int,, longdan long long, dengan beberapa implementasi yang mempromosikan tipe yang lebih pendek dan implementasi lainnya misalnya lmalloc(long n) {return (n < 0 || n > 32767) ? 0 : imalloc(n);}[pada beberapa platform, panggilan ke imalloc(123)akan lebih murah daripada menelepon lmalloc(123);, dan bahkan pada platform di mana size_t16 bit, kode yang ingin mengalokasikan ukuran yang dihitung dalam nilai `long` ...
supercat
... harus dapat mengandalkan alokasi yang gagal jika nilainya lebih besar daripada yang dapat ditangani oleh pengalokasi.
supercat
11
Untuk size_tmengetahui mengapa perlu ada dan bagaimana kita sampai di sini:
Dalam istilah pragmatis, size_tdan ptrdiff_tdijamin selebar 64 bit pada implementasi 64-bit, lebar 32 bit pada implementasi 32-bit, dan seterusnya. Mereka tidak bisa memaksa tipe apa pun yang ada berarti bahwa, pada setiap kompiler, tanpa melanggar kode warisan.
A size_tatau ptrdiff_ttidak harus sama dengan intptr_tatau uintptr_t. Mereka berbeda pada arsitektur tertentu yang masih digunakan kapan size_tdan ptrdiff_tditambahkan ke Standar pada akhir 80-an, dan menjadi usang ketika C99 menambahkan banyak jenis baru tetapi belum hilang (seperti Windows 16-bit). X86 dalam mode terproteksi 16-bit memiliki memori tersegmentasi di mana susunan atau struktur terbesar yang mungkin hanya berukuran 65.536 byte, tetapi farpenunjuk harus lebar 32 bit, lebih lebar dari register. Pada mereka, intptr_takan menjadi lebar 32 bit tetapi size_tdanptrdiff_tbisa 16 bit lebar dan muat dalam register. Dan siapa yang tahu sistem operasi apa yang mungkin ditulis di masa depan? Secara teori, arsitektur i386 menawarkan model segmentasi 32-bit dengan pointer 48-bit yang tidak pernah digunakan oleh sistem operasi.
Jenis offset memori tidak mungkin longkarena terlalu banyak kode lama mengasumsikan bahwa longpersis 32 bit. Asumsi ini bahkan dibangun ke dalam UNIX dan Windows API. Sayangnya, banyak kode lawas lainnya juga berasumsi bahwa a longcukup lebar untuk menampung sebuah pointer, sebuah file offset, jumlah detik yang telah berlalu sejak tahun 1970, dan seterusnya. POSIX sekarang menyediakan cara terstandardisasi untuk memaksakan asumsi yang terakhir menjadi benar, bukan yang sebelumnya, tetapi tidak ada asumsi portabel untuk dibuat.
Itu tidak mungkin intkarena hanya segelintir kompiler di tahun 90-an yang membuat intlebar 64 bit. Kemudian mereka benar-benar aneh dengan menjaga longlebar 32 bit. Revisi Standar berikutnya menyatakan ilegal untuk intmenjadi lebih luas daripada long, tetapi intmasih lebar 32 bit pada kebanyakan sistem 64-bit.
Tidak mungkin long long int, yang bagaimanapun ditambahkan kemudian, karena itu dibuat setidaknya 64 bit lebar bahkan pada sistem 32-bit.
Jadi, diperlukan tipe baru. Bahkan jika tidak, semua tipe lainnya berarti sesuatu selain offset dalam array atau objek. Dan jika ada satu pelajaran dari kegagalan migrasi 32-ke-64-bit, itu harus spesifik tentang properti jenis apa yang perlu dimiliki, dan tidak menggunakan satu yang berarti berbeda dalam program yang berbeda.
Tidak setuju dengan " size_tdan ptrdiff_tdijamin selebar 64 bit pada implementasi 64-bit", dll. Jaminan ini dilebih-lebihkan. Kisaran size_tini terutama didorong oleh kapasitas memori implementasi. "implementasi n-bit" terutama lebar prosesor asli dari bilangan bulat. Tentu saja banyak implementasi menggunakan memori dengan ukuran yang sama dan lebar bus prosesor, tetapi integer asli yang lebar dengan memori yang sedikit atau prosesor yang sempit dengan banyak memori ada dan mendorong kedua properti implementasi ini secara terpisah.
chux
8
size_tdan inttidak bisa dipertukarkan. Misalnya pada 64-bit Linux size_tberukuran 64-bit (yaitu sizeof(void*)) tetapi int32-bit.
Perhatikan juga bahwa size_ttidak ditandatangani. Jika Anda perlu versi yang ditandatangani maka ada ssize_tpada beberapa platform dan itu akan lebih relevan dengan contoh Anda.
Sebagai aturan umum, saya akan menyarankan menggunakan intuntuk sebagian besar kasus umum dan hanya menggunakan size_t/ ssize_tketika ada kebutuhan khusus untuk itu (dengan mmap()misalnya).
Secara umum, jika Anda mulai dari 0 dan naik, selalu gunakan tipe yang tidak ditandatangani untuk menghindari overflow yang membawa Anda ke situasi nilai negatif. Ini sangat penting, karena jika batas array Anda kurang dari maks dari loop Anda, tetapi max loop Anda lebih besar dari max tipe Anda, Anda akan membungkus negatif dan Anda mungkin mengalami kesalahan segmentasi (SIGSEGV ). Jadi, secara umum, jangan pernah gunakan int untuk loop mulai dari 0 dan naik. Gunakan tanda tangan.
Saya tidak dapat menerima argumentasi Anda. Anda mengatakan bahwa lebih baik bug meluap diam-diam mengarah pada mengakses data yang valid dalam array Anda?
maf-soft
1
@ maf-lunak benar. jika kesalahan tidak terdeteksi itu membuatnya lebih buruk daripada crash program. mengapa jawaban ini mendapat suara terbalik?
yoyo_fun
Jika mengakses data yang valid di array Anda maka itu bukan bug karena tipe yang tidak ditandatangani tidak akan meluap pada batas yang ditandatangani tipe yang akan. Logika apa ini? Katakanlah karena alasan tertentu Anda menggunakan char untuk beralih lebih dari 256 elemen array ... ditandatangani akan meluap pada 127 dan elemen 128 akan sigsegv, tetapi jika Anda menggunakan unsigned, maka ia akan melalui seluruh array sebagaimana dimaksud. Kemudian lagi, ketika Anda menggunakan int, array Anda tidak akan benar-benar lebih besar dari 2 miliar elemen jadi apa pun itu tidak masalah ...
Es Ungu
1
Saya tidak bisa membayangkan situasi di mana integer overflow bukan bug, apakah itu membungkus positif atau negatif. Hanya karena Anda tidak mendapatkan segfault bukan berarti Anda melihat perilaku yang benar! Dan Anda dapat mengalami kesalahan segmentasi, atau tidak, apakah offset Anda positif atau negatif; itu semua tergantung pada tata letak memori Anda. @PurpleIce, saya tidak berpikir Anda mengatakan hal yang sama dengan jawaban ini; argumen Anda tampaknya adalah bahwa Anda harus memilih tipe data yang cukup besar untuk menampung nilai terbesar yang ingin Anda masukkan ke dalamnya, yang merupakan akal sehat biasa.
Soren Bjornstad
Yang mengatakan, saya lebih suka menggunakan tipe unsigned untuk indeks loop secara semantik ; jika variabel Anda tidak akan menjadi negatif, maka Anda mungkin juga menunjukkan bahwa dalam tipe yang Anda pilih. Itu juga bisa memungkinkan kompiler untuk menemukan bug di mana nilainya berakhir negatif, meskipun GCC setidaknya cukup mengerikan dalam menemukan kesalahan khusus ini (pada satu kesempatan saya menginisialisasi unsigned ke -1 dan tidak mendapatkan peringatan). Demikian pula, size_t secara semantik cocok untuk indeks array.
Soren Bjornstad
3
size_t adalah tipe data integer yang tidak ditandatangani. Pada sistem yang menggunakan Perpustakaan C GNU, ini akan menjadi unsigned int atau unsigned long int. size_t umumnya digunakan untuk pengindeksan array dan penghitungan loop.
size_t atau tipe yang tidak ditandatangani mungkin terlihat digunakan sebagai variabel loop karena variabel loop biasanya lebih besar dari atau sama dengan 0.
Ketika kita menggunakan objek size_t , kita harus memastikan bahwa dalam semua konteks yang digunakan, termasuk aritmatika, kita hanya menginginkan nilai-nilai non-negatif. Misalnya, program berikut pasti akan memberikan hasil yang tidak terduga:
// C program to demonstrate that size_t or// any unsigned int type should be used // carefully when used in a loop#include<stdio.h>int main(){constsize_t N =10;int a[N];// This is finefor(size_t n =0; n < N;++n)
a[n]= n;// But reverse cycles are tricky for unsigned // types as can lead to infinite loopfor(size_t n = N-1; n >=0;--n)
printf("%d ", a[n]);}OutputInfinite loop and then segmentation fault
size_tadalah tipe data integer yang tidak ditandatangani yang hanya dapat menetapkan 0 dan lebih besar dari 0 nilai integer. Ini mengukur byte dari ukuran objek apa pun dan dikembalikan oleh sizeofoperator.
constadalah representasi sintaks size_t, tetapi tanpa constAnda dapat menjalankan program.
constsize_t number;
size_tsecara teratur digunakan untuk pengindeksan array dan penghitungan loop. Jika kompiler 32-bititu akan bekerja unsigned int. Jika kompiler 64-bititu akan berfungsi unsigned long long intjuga. Ada untuk ukuran maksimum size_ttergantung pada jenis kompiler.
size_tsudah menentukan pada <stdio.h>file header, tetapi juga dapat menentukan oleh
<stddef.h>, <stdlib.h>, <string.h>, <time.h>, <wchar.h>header.
Contoh (dengan const)
#include<stdio.h>int main(){constsize_t value =200;size_t i;int arr[value];for(i =0; i < value ;++i){
arr[i]= i;}size_t size =sizeof(arr);
printf("size = %zu\n", size);}
Output -:size = 800
Contoh (tanpa const)
#include<stdio.h>int main(){size_t value =200;size_t i;int arr[value];for(i =0; i < value ;++i){
arr[i]= i;}size_t size =sizeof(arr);
printf("size = %zu\n", size);}
Tidak benar. Ukuran pointer bisa lebih besar dari size_t. Beberapa contoh: C compiler pada mode real x86 dapat memiliki 32 bit FARatau HUGEpointer tetapi size_t masih 16 bit. Contoh lain: Watcom C dulu memiliki penunjuk lemak khusus untuk memori tambahan yang lebar 48 bit, tetapi size_ttidak. Pada pengontrol tertanam dengan arsitektur Harvard, Anda tidak memiliki korelasi juga, karena keduanya menyangkut ruang alamat yang berbeda.
int
jikasome_size
ditandatangani,size_t
jika tidak ditandatangani.int i
mungkin tidak cukup untuk mengatasi array besar. Jadi dengan menggunakansize_t i
Anda dapat mengatasi lebih banyak indeks, bahkan jika Anda memiliki array besar yang seharusnya tidak menjadi masalah.size_t
adalah tipe data: biasanya aunsigned long int
tetapi ini tergantung pada sistem Anda.Jawaban:
Dari Wikipedia :
Implikasinya,
size_t
adalah jenis yang dijamin untuk menyimpan indeks array apa pun.sumber
size_t
adalah untuk objek dalam memori. Standar C bahkan tidak mendefinisikanstat()
atauoff_t
(itu adalah definisi POSIX) atau ada hubungannya dengan disk atau sistem file - berhenti sendiri diFILE
stream. Manajemen memori virtual benar-benar berbeda dari sistem file dan manajemen file sejauh persyaratan ukuran berjalan, sehingga menyebutkanoff_t
tidak relevan di sini.size_t
sebagai jenis hasil darisizeof
operator (tentang 7.17p2<stddef.h>
). Bagian 6.5 menjelaskan dengan tepat bagaimana ekspresi C bekerja (6.5.3.4 untuksizeof
). Karena Anda tidak dapat menerapkansizeof
ke file disk (kebanyakan karena C bahkan tidak menentukan cara kerja disk dan file), tidak ada ruang untuk kebingungan. Dengan kata lain, salahkan Wikipedia (dan jawaban ini untuk mengutip Wikipedia dan bukan standar C aktual).size_t
adalah tipe yang tidak ditandatangani. Jadi, itu tidak dapat mewakili nilai negatif apa pun (<0). Anda menggunakannya saat menghitung sesuatu, dan yakin itu tidak negatif. Misalnya,strlen()
mengembalikan asize_t
karena panjang string harus minimal 0.Dalam contoh Anda, jika indeks loop Anda akan selalu lebih besar dari 0, mungkin masuk akal untuk digunakan
size_t
, atau tipe data yang tidak ditandatangani lainnya.Ketika Anda menggunakan
size_t
objek, Anda harus memastikan bahwa dalam semua konteks itu digunakan, termasuk aritmatika, Anda menginginkan nilai-nilai non-negatif. Sebagai contoh, katakanlah Anda memiliki:dan Anda ingin menemukan perbedaan panjang
str2
danstr1
. Anda tidak dapat melakukan:Ini karena nilai yang ditetapkan untuk
diff
selalu akan menjadi angka positif, bahkan ketikas2 < s1
, karena perhitungan dilakukan dengan tipe yang tidak ditandatangani. Dalam hal ini, tergantung pada apa use case Anda, Anda mungkin lebih baik menggunakanint
(ataulong long
) untuks1
dans2
.Ada beberapa fungsi dalam C / POSIX yang bisa / harus digunakan
size_t
, tetapi tidak karena alasan historis. Sebagai contoh, parameter keduafgets
seharusnya idealnyasize_t
, tetapi adalahint
.sumber
size_t
? 2) mengapa saya lebih sukasize_t
daripada sesuatu sepertiunsigned int
?size_t
yaitusizeof(size_t)
. Standar C menjaminSIZE_MAX
paling tidak 65535.size_t
adalah jenis yang dikembalikan olehsizeof
operator, dan digunakan di perpustakaan standar (misalnyastrlen
pengembaliansize_t
). Seperti yang dikatakan Brendan,size_t
tidak harus sama denganunsigned int
.size_t
dijamin menjadi tipe yang tidak ditandatangani.s2 - s1
overflowint
, perilaku tidak terdefinisi.size_t
adalah tipe yang bisa menampung indeks array apa pun.Bergantung pada implementasinya, dapat berupa:
unsigned char
unsigned short
unsigned int
unsigned long
unsigned long long
Inilah cara
size_t
didefinisikan distddef.h
mesin saya:sumber
typedef unsigned long size_t
tergantung pada kompiler. Atau apakah Anda menyarankan agar selalu demikian?unsigned long
adalah 32-bit,size_t
adalah 64-bit.size_t
bukan variabel. Ini adalah tipe yang dapat Anda gunakan saat Anda ingin merepresentasikan ukuran objek dalam memori.size_t
selalu 32bits pada mesin 32-bit, 64bits juga?Jika Anda adalah tipe empiris ,
Output untuk Ubuntu 14.04 64-bit GCC 4.8:
Catatan yang
stddef.h
disediakan oleh GCC dan tidak glibcsrc/gcc/ginclude/stddef.h
di bawah dalam GCC 4.2.Penampilan C99 yang menarik
malloc
mengambilsize_t
sebagai argumen, sehingga menentukan ukuran maksimum yang mungkin dialokasikan.Dan karena itu juga dikembalikan oleh
sizeof
, saya pikir itu membatasi ukuran maksimum dari array apa pun.Lihat juga: Berapa ukuran maksimum array dalam C?
sumber
size_t
ada , setidaknya pada distro Linux yang populer.Halaman manual untuk types.h mengatakan:
sumber
Karena belum ada yang menyebutkannya, makna linguistik utama
size_t
adalah bahwasizeof
operator mengembalikan nilai jenis itu. Demikian juga, signifikansi utama dariptrdiff_t
pengurangan satu pointer dari yang lain akan menghasilkan nilai dari jenis itu. Fungsi pustaka yang menerimanya melakukannya karena itu akan memungkinkan fungsi tersebut untuk bekerja dengan objek yang ukurannya melebihi UINT_MAX pada sistem di mana objek tersebut dapat ada, tanpa memaksa penelepon membuang kode yang melewati nilai yang lebih besar dari "unsigned int" pada sistem di mana tipe yang lebih besar akan cukup untuk semua objek yang mungkin.sumber
malloc()
. Secara pribadi, saya ingin melihat versi yang mengambil argumen tipeint
,,long
danlong long
, dengan beberapa implementasi yang mempromosikan tipe yang lebih pendek dan implementasi lainnya misalnyalmalloc(long n) {return (n < 0 || n > 32767) ? 0 : imalloc(n);}
[pada beberapa platform, panggilan keimalloc(123)
akan lebih murah daripada meneleponlmalloc(123);
, dan bahkan pada platform di manasize_t
16 bit, kode yang ingin mengalokasikan ukuran yang dihitung dalam nilai `long` ...Untuk
size_t
mengetahui mengapa perlu ada dan bagaimana kita sampai di sini:Dalam istilah pragmatis,
size_t
danptrdiff_t
dijamin selebar 64 bit pada implementasi 64-bit, lebar 32 bit pada implementasi 32-bit, dan seterusnya. Mereka tidak bisa memaksa tipe apa pun yang ada berarti bahwa, pada setiap kompiler, tanpa melanggar kode warisan.A
size_t
atauptrdiff_t
tidak harus sama denganintptr_t
atauuintptr_t
. Mereka berbeda pada arsitektur tertentu yang masih digunakan kapansize_t
danptrdiff_t
ditambahkan ke Standar pada akhir 80-an, dan menjadi usang ketika C99 menambahkan banyak jenis baru tetapi belum hilang (seperti Windows 16-bit). X86 dalam mode terproteksi 16-bit memiliki memori tersegmentasi di mana susunan atau struktur terbesar yang mungkin hanya berukuran 65.536 byte, tetapifar
penunjuk harus lebar 32 bit, lebih lebar dari register. Pada mereka,intptr_t
akan menjadi lebar 32 bit tetapisize_t
danptrdiff_t
bisa 16 bit lebar dan muat dalam register. Dan siapa yang tahu sistem operasi apa yang mungkin ditulis di masa depan? Secara teori, arsitektur i386 menawarkan model segmentasi 32-bit dengan pointer 48-bit yang tidak pernah digunakan oleh sistem operasi.Jenis offset memori tidak mungkin
long
karena terlalu banyak kode lama mengasumsikan bahwalong
persis 32 bit. Asumsi ini bahkan dibangun ke dalam UNIX dan Windows API. Sayangnya, banyak kode lawas lainnya juga berasumsi bahwa along
cukup lebar untuk menampung sebuah pointer, sebuah file offset, jumlah detik yang telah berlalu sejak tahun 1970, dan seterusnya. POSIX sekarang menyediakan cara terstandardisasi untuk memaksakan asumsi yang terakhir menjadi benar, bukan yang sebelumnya, tetapi tidak ada asumsi portabel untuk dibuat.Itu tidak mungkin
int
karena hanya segelintir kompiler di tahun 90-an yang membuatint
lebar 64 bit. Kemudian mereka benar-benar aneh dengan menjagalong
lebar 32 bit. Revisi Standar berikutnya menyatakan ilegal untukint
menjadi lebih luas daripadalong
, tetapiint
masih lebar 32 bit pada kebanyakan sistem 64-bit.Tidak mungkin
long long int
, yang bagaimanapun ditambahkan kemudian, karena itu dibuat setidaknya 64 bit lebar bahkan pada sistem 32-bit.Jadi, diperlukan tipe baru. Bahkan jika tidak, semua tipe lainnya berarti sesuatu selain offset dalam array atau objek. Dan jika ada satu pelajaran dari kegagalan migrasi 32-ke-64-bit, itu harus spesifik tentang properti jenis apa yang perlu dimiliki, dan tidak menggunakan satu yang berarti berbeda dalam program yang berbeda.
sumber
size_t
danptrdiff_t
dijamin selebar 64 bit pada implementasi 64-bit", dll. Jaminan ini dilebih-lebihkan. Kisaransize_t
ini terutama didorong oleh kapasitas memori implementasi. "implementasi n-bit" terutama lebar prosesor asli dari bilangan bulat. Tentu saja banyak implementasi menggunakan memori dengan ukuran yang sama dan lebar bus prosesor, tetapi integer asli yang lebar dengan memori yang sedikit atau prosesor yang sempit dengan banyak memori ada dan mendorong kedua properti implementasi ini secara terpisah.size_t
danint
tidak bisa dipertukarkan. Misalnya pada 64-bit Linuxsize_t
berukuran 64-bit (yaitusizeof(void*)
) tetapiint
32-bit.Perhatikan juga bahwa
size_t
tidak ditandatangani. Jika Anda perlu versi yang ditandatangani maka adassize_t
pada beberapa platform dan itu akan lebih relevan dengan contoh Anda.Sebagai aturan umum, saya akan menyarankan menggunakan
int
untuk sebagian besar kasus umum dan hanya menggunakansize_t
/ssize_t
ketika ada kebutuhan khusus untuk itu (denganmmap()
misalnya).sumber
Secara umum, jika Anda mulai dari 0 dan naik, selalu gunakan tipe yang tidak ditandatangani untuk menghindari overflow yang membawa Anda ke situasi nilai negatif. Ini sangat penting, karena jika batas array Anda kurang dari maks dari loop Anda, tetapi max loop Anda lebih besar dari max tipe Anda, Anda akan membungkus negatif dan Anda mungkin mengalami kesalahan segmentasi (SIGSEGV ). Jadi, secara umum, jangan pernah gunakan int untuk loop mulai dari 0 dan naik. Gunakan tanda tangan.
sumber
size_t adalah tipe data integer yang tidak ditandatangani. Pada sistem yang menggunakan Perpustakaan C GNU, ini akan menjadi unsigned int atau unsigned long int. size_t umumnya digunakan untuk pengindeksan array dan penghitungan loop.
sumber
size_t atau tipe yang tidak ditandatangani mungkin terlihat digunakan sebagai variabel loop karena variabel loop biasanya lebih besar dari atau sama dengan 0.
Ketika kita menggunakan objek size_t , kita harus memastikan bahwa dalam semua konteks yang digunakan, termasuk aritmatika, kita hanya menginginkan nilai-nilai non-negatif. Misalnya, program berikut pasti akan memberikan hasil yang tidak terduga:
sumber
size_t
adalah tipe data integer yang tidak ditandatangani yang hanya dapat menetapkan 0 dan lebih besar dari 0 nilai integer. Ini mengukur byte dari ukuran objek apa pun dan dikembalikan olehsizeof
operator.const
adalah representasi sintakssize_t
, tetapi tanpaconst
Anda dapat menjalankan program.size_t
secara teratur digunakan untuk pengindeksan array dan penghitungan loop. Jika kompiler32-bit
itu akan bekerjaunsigned int
. Jika kompiler64-bit
itu akan berfungsiunsigned long long int
juga. Ada untuk ukuran maksimumsize_t
tergantung pada jenis kompiler.size_t
sudah menentukan pada<stdio.h>
file header, tetapi juga dapat menentukan oleh<stddef.h>
,<stdlib.h>
,<string.h>
,<time.h>
,<wchar.h>
header.const
)Output -:
size = 800
const
)Output -:
size = 800
sumber
Dari pemahaman saya,
size_t
adalahunsigned
bilangan bulat yang ukuran bitnya cukup besar untuk menampung pointer dari arsitektur asli.Begitu:
sumber
size_t
. Beberapa contoh: C compiler pada mode real x86 dapat memiliki 32 bitFAR
atauHUGE
pointer tetapi size_t masih 16 bit. Contoh lain: Watcom C dulu memiliki penunjuk lemak khusus untuk memori tambahan yang lebar 48 bit, tetapisize_t
tidak. Pada pengontrol tertanam dengan arsitektur Harvard, Anda tidak memiliki korelasi juga, karena keduanya menyangkut ruang alamat yang berbeda.size_t