Perbedaan antara size_t dan std :: size_t

143

Apa perbedaan antara size_tdan std::size_tdalam hal di mana mereka dideklarasikan, kapan harus digunakan dan fitur pembeda lainnya?

Mankarse
sumber
Saya tertarik untuk mengetahui apakah spesifikasi C ++ menghubungkan std :: size_t ke tipe C size_t.
Doug T.
Lihat pertanyaan serupa: link
Mankarse

Jawaban:

91

C size_tdan C ++ std::size_tkeduanya sama.

Di C, itu didefinisikan dalam <stddef.h>dan di C ++, itu didefinisikan <cstddef>yang isinya sama dengan header C (lihat kutipan di bawah). Its didefinisikan sebagai tipe unsigned integer dari hasil dari sizeof operator.

C Standard mengatakan dalam §17.7 / 2,

size_t yang merupakan tipe integer unsigned dari hasil dari sizeof Operator

Dan C ++ Standard mengatakan (tentang cstddefheader) di §18.1 / 3,

Kontennya sama dengan header pustaka C Standar, dengan perubahan berikut ini .

Jadi ya, keduanya sama; satu-satunya perbedaan adalah bahwa C ++ mendefinisikan size_tdi stdnamespace.

Harap perhatikan juga bahwa baris di atas juga mengatakan "dengan perubahan berikut" yang tidak mengacu pada size_t. Ini lebih mengacu pada penambahan baru (kebanyakan) yang dibuat oleh C ++ ke dalam bahasa (tidak ada di C) yang juga didefinisikan di header yang sama.


Wikipedia memiliki info yang sangat bagus tentang jangkauan dan ukuran penyimpanan size_t:

Rentang dan ukuran penyimpanan size_t

The aktual jenis size_t adalah tergantung platform ; sebuah kesalahan umum adalah dengan mengasumsikan size_t adalah sama dengan int unsigned, yang dapat menyebabkan kesalahan pemrograman, [3] [4] ketika bergerak dari 32 ke arsitektur 64-bit, misalnya.

Menurut standar ISO C 1999 (C99), size_t adalah jenis bilangan bulat unsigned setidaknya 16 bit.

Dan selebihnya Anda dapat membaca dari halaman ini di wikipedia.

Nawaz
sumber
Itu membawa ke Q lain, Jika STL sudah mengimpor size_t melalui C (cstddef) mengapa ia memiliki versi lain lagi?
Alok Save
43
@Als: Sebenarnya, ini adalah kesalahan untuk mengatakan size_ttanpa using namespace std;atau using std::size_t;. Namun, sebagian besar kompiler mengizinkannya, dan Standar secara khusus mengizinkan mereka untuk mengizinkannya (§D.5 / 3).
Potatoswatter
9
@ Potatoswatter: Tentunya itu tidak bisa menjadi kesalahan dan secara khusus diperbolehkan dalam standar? Kalau sudah standar, itu bukan error!
Ben Hymers
9
@BenHymers Standar menentukan apa yang dideklarasikan oleh header standar, dan mereka tidak diperbolehkan untuk mendeklarasikan nama non-reserved lainnya. Header <cstddef>mungkin atau mungkin tidak mendeklarasikan ::size_t, jadi Anda tidak bisa mengandalkannya ada atau tidak ada, kecuali secara khusus menyertakan <stddef.h>atau header lain dari pustaka C yang dijamin untuk mendeklarasikannya.
Potatoswatter
4
@Potatoswatter: Ah, saya mengerti apa yang Anda maksud sekarang! Saya pasti bingung dengan terlalu banyak kata "allow" dalam satu kalimat. Saya masih berpikir komentar pertama Anda terlalu kuat; seperti yang baru saja Anda katakan, ::size_tada misalnya di <stddef.h>, jadi Anda tidak selalu perlu membuatnya memenuhi syarat std::.
Ben Hymers
16

Dari C ++ 03 "17.4.3.1.4 Jenis":

Untuk setiap tipe T dari pustaka C Standar (catatan kaki 169), tipe :: T dan std :: T dicadangkan untuk implementasi dan, bila ditentukan, :: T harus identik dengan std :: T.

Dan catatan kaki 169:

Jenis ini adalah clock_t, div_t, FILE, fpos_t, lconv, ldiv_t, mbstate_t, ptrdiff_t, sig_atomic_t, size_t, time_t, tm, va_list, wctrans_t, wctype_t, dan wint_t.

Michael Burr
sumber
Jadi kode portabel tidak harus bergantung pada std::Tvarian yang ditentukan?
Mankarse
6
@Mankarse: Anda tidak boleh mengandalkan definisi mereka jika Anda hanya menyertakan versi C dari header yang sesuai. Jika Anda #include <stddef.h>kemudian std::size_tmungkin atau mungkin tidak tersedia. Jika Anda #include <cstddef>kemudian std::size_ttersedia, tetapi size_tmungkin tidak.
Dennis Zickefoose
4
@Mankarse: Lawannya. Header versi C ++ harus mendefinisikannya dalam std::dan paragraf mengatakan bahwa ia juga dapat mendefinisikannya di namespace tingkat atas dan jika ya, ia harus mendefinisikannya secara identik di dalam std::dan tingkat atas. Sebagian besar kompiler hanya menyertakan header C dan mengimpor nama ke std::, sehingga simbol akhirnya ditentukan di keduanya.
Jan Hudec
4
Secara pribadi, saya tidak pernah peduli dengan <cxxxxx> header atau std::varian pengenal yang berasal dari pantai C. Saya tetap menggunakan <xxxxx.h>untuk header C standar - itu tidak pernah menjadi masalah. Jadi, saya akan menggunakan <stddef.h>dan size_tdan tidak pernah berpikir dua kali untuk std::size_t; pada kenyataannya, tidak pernah terlintas dalam pikiran saya bahwa ada (atau mungkin) a std::size_t.
Michael Burr
14

std :: size_t sebenarnya stddef.h 's size_t .

cstddef memberikan yang berikut:

#include <stddef.h>
namespace std 
{
  using ::ptrdiff_t;
  using ::size_t;
}

... secara efektif membawa definisi sebelumnya ke namespace std.

pengikat
sumber
Seperti yang ditunjukkan Nawaz, sebenarnya yang terjadi adalah sebaliknya. Anda tidak dapat memasukkan <cstddef>dan mengharapkan untuk mendapatkan ::size_t, tetapi jika Anda memasukkan <stddef.h>Anda akan mendapatkan std::size_t.
MSalters
4
@ MSalters, saya tidak mengikuti. Termasuk <stddef.h>hanya akan membuatmu ::size_t.
hifier
2
Itu adalah bug dalam implementasi Anda.
MSalters
4
@ MSalters, saya kurang mengikuti. Bukankah seharusnya sebaliknya? <cstddef> berasal dari C ++, jadi harus mendefinisikan hal-hal di std :: *? Di sisi lain, dalam header C, seperti stddef.h, saya hanya mengharapkan tipe C, yaitu :: size_t.
Ela782
12
@MSalters, karena C ++ 11 itu tidak akurat. Jika Anda memasukkan <cstddef>Anda dijamin untuk mendapatkan std::size_tdan Anda mungkin juga mendapatkan ::size_t(tapi itu tidak dijamin). Jika Anda memasukkan <stddef.h>Anda dijamin akan mendapatkan ::size_tdan Anda mungkin juga mendapatkan std::size_t(tapi itu tidak dijamin). Itu berbeda di C ++ 03 tetapi itu secara efektif tidak dapat diterapkan dan diperbaiki sebagai cacat.
Jonathan Wakely