Apa standar C ++ yang menyatakan ukuran int, tipe panjang menjadi?

696

Saya mencari informasi terperinci mengenai ukuran tipe dasar C ++. Saya tahu bahwa itu tergantung pada arsitektur (16 bit, 32 bit, 64 bit) dan kompiler.

Tetapi apakah ada standar untuk C ++?

Saya menggunakan Visual Studio 2008 pada arsitektur 32-bit. Inilah yang saya dapatkan:

char  : 1 byte
short : 2 bytes
int   : 4 bytes
long  : 4 bytes
float : 4 bytes
double: 8 bytes

Saya mencoba mencari, tanpa banyak keberhasilan, informasi yang dapat dipercaya menyatakan ukuran char, short, int, long, double, float(dan jenis lain saya tidak memikirkan) di bawah arsitektur yang berbeda dan compiler.

Jérôme
sumber
18
@thyrgle bukan karena pilihan ... ada begitu banyak arsitektur yang perlu didukung sehingga harus fleksibel.
Krakkos
4
Mengapa mereka tidak menghapus semua jenis yang tidak jelas, dan menstandarkan semuanya untuk jenis panjang bit tertentu misalnya int32_t, uint32_t, int64_t dll.
developerbmw
5
@thyrgle Sebenarnya cukup sulit untuk menstandarkan sesuatu seperti ini. Tidak seperti Java, di mana hal-hal ini konstan karena cara kerja JVM, C / C ++ pada dasarnya harus berpegang pada sistem yang mereka jalankan tanpa lapisan abstraksi fancy-pancy (setidaknya tidak sebanyak dengan Java) di antara. Jika ukuran int adalah yang penting dapat digunakan int16_t, int32_tdan int64_t(perlu iostreammenyertakan untuk itu jika saya ingat dengan benar). Apa yang baik tentang ini bahwa int64_t seharusnya tidak memiliki masalah pada sistem 32bit (ini akan mempengaruhi kinerja).
rbaleksandar
5
@rbaleksandar Mereka sebenarnya didefinisikan <cstdint>, bukan <iostream>.
Justin Time - Pasang kembali Monica

Jawaban:

685

Standar C ++ tidak menentukan ukuran tipe integral dalam byte, tetapi menentukan rentang minimum yang harus dapat dipegang. Anda dapat menyimpulkan ukuran minimum dalam bit dari rentang yang diperlukan. Anda dapat menyimpulkan ukuran minimum dalam byte dari itu dan nilai CHAR_BITmakro yang mendefinisikan jumlah bit dalam byte . Dalam semua platform kecuali yang paling tidak jelas itu 8, dan tidak boleh kurang dari 8. Itu karena itu harus cukup besar untuk menampung "unit kode delapan-bit dari bentuk pengkodean Unicode UTF-8."

Satu kendala tambahan charadalah ukurannya selalu 1 byte, atau CHAR_BITbit (karena itu namanya). Ini dinyatakan secara eksplisit dalam standar.

Standar C adalah referensi normatif untuk standar C ++, jadi meskipun tidak menyatakan persyaratan ini secara eksplisit, C ++ memerlukan rentang minimum yang disyaratkan oleh standar C (halaman 22), yang sama dengan yang berasal dari Tipe Data Mulai dari MSDN :

  1. signed char: -127 hingga 127 (catatan, bukan -128 hingga 127; ini mengakomodasi platform 1-pelengkap dan tanda-dan-besarnya)
  2. unsigned char: 0 hingga 255
  3. "polos" char: rentang yang sama dengan signed charatau unsigned char, didefinisikan oleh implementasi
  4. signed short: -32767 hingga 32767
  5. unsigned short: 0 hingga 65535
  6. signed int: -32767 hingga 32767
  7. unsigned int: 0 hingga 65535
  8. signed long: -2147483647 hingga 2147483647
  9. unsigned long: 0 hingga 4294967295
  10. signed long long: -9223372036854775807 hingga 9223372036854775807
  11. unsigned long long: 0 hingga 18446744073709551615

Implementasi C ++ (atau C) dapat menentukan ukuran tipe dalam byte sizeof(type)ke nilai apa pun, asalkan

  1. ekspresi sizeof(type) * CHAR_BITmengevaluasi sejumlah bit yang cukup tinggi untuk memuat rentang yang diperlukan, dan
  2. pemesanan tipe masih valid (mis sizeof(int) <= sizeof(long).).

Menyatukan semua ini, kami dijamin bahwa:

  • char,, signed chardan unsigned charsetidaknya 8 bit
  • signed short, unsigned short, signed int, Dan unsigned intsetidaknya 16 bit
  • signed longdan unsigned longsetidaknya 32 bit
  • signed long longdan unsigned long longsetidaknya 64 bit

Tidak ada jaminan dibuat tentang ukuran floatatau doublekecuali yang doublememberikan setidaknya setepat sebanyak float.

Rentang implementasi spesifik aktual dapat ditemukan di <limits.h>header di C, atau <climits>di C ++ (atau bahkan lebih baik, templated std::numeric_limitsdi <limits>header).

Misalnya, ini adalah bagaimana Anda akan menemukan rentang maksimum untuk int:

C:

#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;

C ++ :

#include <limits>
const int min_int = std::numeric_limits<int>::min();
const int max_int = std::numeric_limits<int>::max();
Alex B
sumber
49
Sebaliknya, standar C ++ menggunakan byte kata yang berarti "1 char", dan bukan arti yang biasa.
Ben Voigt
4
@Programmer Baca jawabannya (catatan 1 dalam tanda kurung), atau kata-kata standar aktual (ditautkan dalam jawaban). Standar C mengakomodasi arsitektur komplemen 1, yang memiliki representasi berbeda dari komplemen 2 yang paling luas. Rentang minimum yang dijamin hampir selalu berbeda dari rentang aktual yang disediakan oleh implementasi.
Alex B
9
@Alex B Anda tidak menyebutkan apa pun tentang jawaban ganda dalam jawaban Anda. Bisakah Anda memperbarui jawaban Anda untuk variabel floating point?
Cool_Coder
3
@ Cool_Coder: Titik apung adalah ketel ikan tambahan, dengan mudah menggandakan ukuran tulisan.
Deduplicator
3
@Mooing Duck: "semua versi C ++ memerlukan 256 nilai berbeda [untuk tipe char yang ditandatangani]" Tidak, itu tidak benar sampai diperbaiki di spesifikasi C ++ yang lebih baru. Spesifikasi yang lebih lama memungkinkan tipe char yang ditandatangani memiliki pola bit yang tidak memetakan ke nomor, sehingga mereka kehilangan persyaratan bahwa ada 256 nilai yang berbeda. "Untuk tipe karakter yang tidak ditandatangani, semua pola bit yang mungkin dari representasi nilai mewakili angka. Persyaratan ini tidak berlaku untuk tipe lainnya."
Adrian McCarthy
241

Untuk sistem 32-bit, standar 'de facto' adalah ILP32 - yaitu int,, longdan pointer semuanya berjumlah 32-bit.

Untuk sistem 64-bit, standar utama Unix 'de facto' adalah LP64 - longdan penunjuknya adalah 64-bit (tetapi int32-bit). Windows 64-bit standar LLP64 - long longdan pointer adalah 64-bit (tapi longdan intyang kedua 32-bit).

Pada suatu waktu, beberapa sistem Unix menggunakan organisasi ILP64.

Tidak satu pun dari standar de facto ini yang diundangkan oleh standar C (ISO / IEC 9899: 1999), tetapi semua diizinkan olehnya.

Dan, menurut definisi, sizeof(char)adalah 1, terlepas dari pengujian dalam skrip konfigurasikan Perl.

Perhatikan bahwa ada mesin (Crays) di mana CHAR_BITjauh lebih besar dari 8. Itu berarti, IIRC, sizeof(int)itu juga 1, karena keduanya chardan int32-bit.

Jonathan Leffler
sumber
73
1 untuk menyatakan bagaimana hal-hal sebenarnya dalam kasus-kasus yang paling berarti bagi, daripada bagaimana hal-hal dalam teori. Jika Anda ingin penggunaan 32bit int, jika Anda ingin menggunakan panjang 64bit. Jika Anda ingin menggunakan asli size_t. Hindari "polos" panjang karena bervariasi. Itu seharusnya bekerja untuk sebagian besar aplikasi.
Eloff
37
+1 untuk jawabannya. @ Eloff: sebaliknya ... jika Anda ingin menggunakan 32 bit [u]int32_tatau serupa, jika Anda ingin menggunakan 64 bit [u]int64_t... jika Anda tidak memiliki header untuk mereka, unduh atau buat, sebaiknya dengan kompilasi waktu pemilihan jenis atau pernyataan statis untuk memverifikasi ukuran. pubs.opengroup.org/onlinepubs/009695299/basedefs/stdint.h.html Jika ukuran yang tepat tidak begitu penting dan Anda hanya peduli mereka setidaknya sebesar itu, maka saran Anda berlaku untuk platform PC / server modern yang umum.
Tony Delroy
8
Perhatikan bahwa ini bukan hanya mesin cray tua yang memiliki CHAR_BIT> 8. mis. DSP sering memiliki CHAR_BIT 16 atau 32. (lihat misalnya ini )
nos
2
@nos: Terima kasih atas tautannya. Sangat membantu untuk memiliki sistem modern, saat ini diidentifikasi untuk kasus-kasus aneh. Karena penasaran, apa kode yang ditetapkan pada mesin-mesin itu? Jika set kode adalah UTF-16, maka 0xFFFF bukan karakter yang valid, dan jika set kode adalah set kode ISO 8859-x, maka sekali lagi 0xFFFF bukan karakter yang valid (kode karakter dari 0x00 hingga 0xFF valid). Saya belum yakin bahwa ada masalah dalam mendeteksi EOF, tetapi pasti ada ruang untuk berhati-hati, dan mungkin untuk menulis dan menggunakan fungsi int get_char(FILE *fp, char *c)yang mengembalikan EOF atau 0 dan set *c.
Jonathan Leffler
2
@ joelw: C11 mensyaratkan bahwa, mengingat uint32_t x=1,y=2;nilai x-yharus 4294967295 pada platform di mana "int" adalah 32 bit atau lebih kecil, dan -1 pada platform di mana "int" adalah 33 bit atau lebih besar. Lebih jauh lagi, diperlukan bahwa x*yharus dievaluasi menggunakan modular aritmatika untuk semua nilai x dan y jika "int" adalah 32 bit atau lebih kecil, dan aritmatika konvensional jika 65 bit atau lebih besar, tetapi tidak menempatkan persyaratan apa pun pada apa yang mungkin terjadi dengan nilai besar dari x dan y jika "int" adalah 33 hingga 64 bit.
supercat
88

Dalam prakteknya tidak ada hal seperti itu. Seringkali Anda bisa berharapstd::size_t mewakili ukuran integer asli yang tidak ditandatangani pada arsitektur saat ini. yaitu 16-bit, 32-bit atau 64-bit tetapi tidak selalu seperti yang ditunjukkan dalam komentar untuk jawaban ini.

Sejauh semua tipe bawaan lainnya berjalan, itu benar-benar tergantung pada kompiler. Berikut adalah dua kutipan yang diambil dari draft kerja standar C ++ terbaru:

Ada lima tipe integer bertanda tangan standar: char yang ditandatangani, int pendek, int, int panjang, dan int panjang panjang. Dalam daftar ini, masing-masing jenis menyediakan penyimpanan setidaknya sebanyak yang sebelumnya dalam daftar.

Untuk masing-masing tipe integer bertanda tangan standar, terdapat tipe integer unsigned standar (tapi berbeda) yang sesuai: char unsigned, unsigned short int, unsigned int, unsigned long int, dan unsigned long int, masing-masing menempati jumlah yang sama penyimpanan dan memiliki persyaratan pelurusan yang sama.

Jika Anda mau, Anda dapat secara statis (waktu kompilasi) menyatakan ukuran dari tipe-tipe mendasar ini. Ini akan mengingatkan orang untuk berpikir tentang porting kode Anda jika ukuran asumsi berubah.

John Leidegren
sumber
7
pos yang bagus. Hal lain yang diperlukan adalah ukuran bit paling tidak sebagai berikut (didokumentasikan dalam c89 / c99 bersama dengan limit.h dan diambil alih oleh c ++): char> = 8, pendek dan int> = 16, panjang> = 32.
Johannes Schaub - litb
1
Juga, pada platform AVR 8 bit size_t tidak akan menjadi 8 bit, tetapi 16, karena ukuran pointer dan int adalah 16 bit. Jadi ukuran data asli prosesor tidak terkait dengan size_t.
Robotbugs
80

Ada standar.

Standar C90 mensyaratkan itu

sizeof(short) <= sizeof(int) <= sizeof(long)

Standar C99 mensyaratkan itu

sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)

Berikut adalah spesifikasi C99 . Halaman 22 merinci ukuran berbagai tipe integral.

Berikut adalah ukuran tipe int (bit) untuk platform Windows:

Type           C99 Minimum     Windows 32bit
char           8               8
short          16              16
int            16              32
long           32              32
long long      64              64

Jika Anda khawatir dengan portabilitas, atau Anda ingin nama tipe mencerminkan ukuran, Anda dapat melihat headernya <inttypes.h>, di mana makro berikut tersedia:

int8_t
int16_t
int32_t
int64_t

int8_tdijamin 8 bit, dan int16_tdijamin 16 bit, dll.

yinyueyouge
sumber
8
Minor nitpick: di mana standar mengatakan sizeof(long) < sizeof(long long)berlawanan dengan simetris sizeof(long) <= sizeof(long long)?
Jonathan Leffler
2
@ JonathonLeffler - lihat C99 5.2.4.2.1 - Ukuran tipe integer. minsizeof (int) == 16-bit, minsizeof (panjang) == 32-bit, minsizeof (panjang panjang) == 64-bit. Jadi saya pikir Anda benar pada <= karena tidak ada maxsizeof (tipe) yang ditentukan.
Jesse Chisholm
Demikian pula sizeof (float) <= sizeof (double) <= sizeof (long double). Menurut C99 7.12 paragraf 2.
Jesse Chisholm
38

Jika Anda membutuhkan tipe ukuran tetap, gunakan tipe seperti uint32_t (unsigned integer 32 bits) yang didefinisikan di stdint.h . Mereka ditentukan dalam C99 .

Ben
sumber
10
Mereka ditentukan tetapi tidak diperlukan.
dreamlax
2
@dreamlax Platform apa yang tidak termasuk?
Levi Morrison
3
@LeviMorrison: Platform apa pun yang tidak memilikinya dalam bentuk yang diperlukan. Sebuah platform yang CHAR_BIT == 16, misalnya, tidak akan miliki int8_t. Platform tidak menggunakan komplemen tidak akan memiliki setiap dari mereka (sebagai komplemen diperlukan oleh standar).
DevSolar
36

Diperbarui: C ++ 11 membawa tipe-tipe dari TR1 secara resmi ke dalam standar:

  • int panjang
  • unsigned long int panjang

Dan jenis "berukuran" dari <cstdint>

  • int8_t
  • int16_t
  • int32_t
  • int64_t
  • (dan mitra yang tidak ditandatangani).

Plus Anda mendapatkan:

  • int_least8_t
  • int_least16_t
  • int_least32_t
  • int_least64_t
  • Ditambah mitra yang tidak ditandatangani.

Tipe-tipe ini mewakili tipe integer terkecil dengan setidaknya jumlah bit yang ditentukan. Demikian juga ada tipe integer "tercepat" dengan setidaknya jumlah bit yang ditentukan:

  • int_fast8_t
  • int_fast16_t
  • int_fast32_t
  • int_fast64_t
  • Ditambah versi yang tidak ditandatangani.

Apa yang dimaksud dengan "cepat", jika ada, terserah implementasi. Tidak perlu menjadi yang tercepat untuk semua keperluan juga.

Brian Neal
sumber
Ini adalah bagian dari standar C ++ 11 sekarang.
Jaan
2
"Cepat" hanya berarti disesuaikan dengan arsitektur perangkat keras. Jika register 16-bit, maka int_fast8_t adalah nilai 16-bit. Jika register adalah 32-bit, maka int_fast8_t dan int_fast16_t keduanya adalah nilai 32-bit. dll. Lihat C99 bagian 7.18.1.3 paragraf 2.
Jesse Chisholm
19

Standar C ++ mengatakannya seperti ini:

3.9.1, §2:

Ada lima tipe integer yang ditandatangani: "char yang ditandatangani", "int pendek", "int", "int panjang", dan "int panjang panjang". Dalam daftar ini, masing-masing jenis menyediakan penyimpanan setidaknya sebanyak yang sebelumnya dalam daftar. Int polos memiliki ukuran alami yang disarankan oleh arsitektur lingkungan eksekusi (44); tipe integer yang ditandatangani lainnya disediakan untuk memenuhi kebutuhan khusus.

(44) yaitu, cukup besar untuk memuat nilai apa pun dalam kisaran INT_MIN dan INT_MAX, sebagaimana didefinisikan dalam header <climits> .

Kesimpulannya: Itu tergantung pada arsitektur yang sedang Anda kerjakan. Asumsi lain salah.

Jérôme Radix
sumber
12

Tidak, tidak ada standar untuk ukuran tipe. Standar hanya mensyaratkan bahwa:

sizeof(short int) <= sizeof(int) <= sizeof(long int)

Hal terbaik yang dapat Anda lakukan jika Anda ingin variabel ukuran tetap adalah menggunakan makro seperti ini:

#ifdef SYSTEM_X
  #define WORD int
#else
  #define WORD long int
#endif

Kemudian Anda bisa menggunakan WORD untuk mendefinisikan variabel Anda. Bukannya saya suka ini tapi ini cara yang paling portabel .

Emiliano
sumber
4
Masalahnya adalah bahwa WORD tersebar di sekitar program ke daerah-daerah yang tidak benar-benar bergantung pada ukuran tetap (lihat beberapa kode windows). Seperti yang saya temukan ketika pindah dari sistem 16 bit ke 32 bit Anda berakhir dengan masalah yang sama yang dimaksudkan untuk memecahkan KATA.
lilburne
@ Liburne Tentu saja Anda harus menggunakan WORD hanya ketika Anda membutuhkan variabel ukuran tetap, seperti ketika Anda membaca / menulis dari / ke file. Jika sepotong kode tidak benar-benar tergantung dari ukuran tetap, maka Anda harus menggunakan variabel "int" normal.
Emiliano
3
Hal terbaik yang dapat Anda lakukan untuk mendapatkan ukuran portabel adalah#include <boost/cstdint.hpp>
kizzx2
11

Kami diizinkan untuk menentukan sinonim untuk jenis sehingga kami dapat membuat "standar" kami sendiri.

Pada mesin di mana sizeof (int) == 4, kita dapat mendefinisikan:

typedef int int32;

int32 i;
int32 j;
...

Jadi ketika kita mentransfer kode ke mesin yang berbeda di mana sebenarnya ukuran int panjang adalah 4, kita bisa mendefinisikan ulang kejadian int tunggal.

typedef long int int32;

int32 i;
int32 j;
...
milan-j
sumber
1
Itu tidak perlu diberikan tajuk standar <stdint.h>(C99 dan yang lebih baru, dan mana pun standar C ++ yang mengadopsi versi C99 dari pustaka C).
Keith Thompson
8

Untuk angka floating point ada standar (IEEE754) : floats adalah 32 bit dan double adalah 64. Ini adalah standar perangkat keras, bukan standar C ++, jadi kompiler secara teoritis dapat mendefinisikan float dan double ke beberapa ukuran lain, tetapi dalam praktiknya saya ' Saya belum pernah melihat arsitektur yang menggunakan sesuatu yang berbeda.

Crashworks
sumber
2
Namun, kepatuhan dengan IEEE 754 (alias IEC 559) adalah opsional dalam C ++ (mungkin C juga, tapi saya tidak yakin). Lihat std :: numeric_limits :: is_iec559.
Drew Hall
1
Maka Anda belum melihat kompiler TI untuk TMS320C28xx DSP, di mana doublememiliki ukuran yang sama float(dan intsama seperti char, keduanya 16 bit). Tetapi mereka memiliki 64 bit long double.
starblue
7

Ada standar dan ditentukan dalam berbagai dokumen standar (ISO, ANSI dan yang lainnya).

Wikipedia memiliki halaman yang bagus menjelaskan berbagai jenis dan maks yang dapat mereka simpan: Integer dalam Ilmu Komputer.

Namun bahkan dengan kompiler C ++ standar Anda dapat mengetahuinya dengan relatif mudah menggunakan potongan kode berikut:

#include <iostream>
#include <limits>


int main() {
    // Change the template parameter to the various different types.
    std::cout << std::numeric_limits<int>::max() << std::endl;
}

Dokumentasi untuk std :: numeric_limits dapat ditemukan di Roguewave . Ini termasuk sejumlah perintah lain yang dapat Anda panggil untuk mengetahui berbagai batasan. Ini dapat digunakan dengan jenis sembarang yang menyampaikan ukuran, misalnya std :: streamsize.

Jawaban John berisi deskripsi terbaik, karena dijamin akan tetap berlaku. Tidak peduli platform apa yang Anda gunakan, ada halaman bagus lain yang menjelaskan lebih detail berapa banyak bit yang masing-masing harus isi: tipe int , yang didefinisikan dalam standar.

Saya harap ini membantu!

X-Istence
sumber
7

Kamu bisa menggunakan:

cout << "size of datatype = " << sizeof(datatype) << endl;

datatype = int, long intdll. Anda akan dapat melihat ukuran untuk tipe data apa pun yang Anda ketikkan.

Populasi Xplosif
sumber
7

Ketika datang ke tipe built in untuk arsitektur yang berbeda dan kompiler yang berbeda jalankan saja kode berikut pada arsitektur Anda dengan kompiler Anda untuk melihat apa yang dihasilkannya. Di bawah ini menunjukkan keluaran Ubuntu 13.04 (Raring Ringtail) 64 bit g ++ 4.7.3 saya. Harap perhatikan juga apa yang dijawab di bawah ini sehingga outputnya dipesan seperti ini:

"Ada lima tipe integer bertanda tangan standar: char yang ditandatangani, int pendek, int, int panjang, dan int panjang. Dalam daftar ini, masing-masing jenis menyediakan penyimpanan setidaknya sebanyak yang sebelumnya dalam daftar."

#include <iostream>

int main ( int argc, char * argv[] )
{
  std::cout<< "size of char: " << sizeof (char) << std::endl;
  std::cout<< "size of short: " << sizeof (short) << std::endl;
  std::cout<< "size of int: " << sizeof (int) << std::endl;
  std::cout<< "size of long: " << sizeof (long) << std::endl;
  std::cout<< "size of long long: " << sizeof (long long) << std::endl;

  std::cout<< "size of float: " << sizeof (float) << std::endl;
  std::cout<< "size of double: " << sizeof (double) << std::endl;

  std::cout<< "size of pointer: " << sizeof (int *) << std::endl;
}


size of char: 1
size of short: 2
size of int: 4
size of long: 8
size of long long: 8
size of float: 4
size of double: 8
size of pointer: 8
bjackfly
sumber
sizeof(char)seharusnya tidak dimasukkan.
Ven
3

Seperti disebutkan ukurannya harus mencerminkan arsitektur saat ini. Anda dapat mengambil puncak di limits.hjika Anda ingin melihat bagaimana kompiler Anda saat ini menangani hal-hal.

John T
sumber
Terima kasih, tapi saya ingin tahu ukuran untuk arsitektur saya tidak punya myselft (seperti 64bits). Tutorial ini hanya berbicara tentang 32bit arsitektur ...
Jérôme
2

Seperti yang dijawab oleh orang lain, "standar" semuanya meninggalkan sebagian besar detail sebagai "implementasi yang ditentukan" dan hanya menyatakan bahwa tipe "char" setidaknya "char_bis" lebar, dan "char <= short <= int <= long < = long long "(float dan double cukup konsisten dengan standar floating point IEEE, dan double panjang biasanya sama dengan double - tetapi mungkin lebih besar pada implementasi yang lebih terkini).

Sebagian alasan untuk tidak memiliki nilai yang sangat spesifik dan tepat adalah karena bahasa seperti C / C ++ dirancang untuk portabel ke sejumlah besar platform perangkat keras - Termasuk sistem komputer di mana ukuran kata "char" mungkin 4-bit atau 7-bit, atau bahkan beberapa nilai selain dari komputer "8- / 16- / 32- / 64-bit" yang biasa dilihat oleh pengguna komputer rumahan. (Word-size di sini berarti berapa banyak bit lebar sistem biasanya beroperasi - Sekali lagi, itu tidak selalu 8-bit seperti yang diharapkan oleh pengguna komputer di rumah.)

Jika Anda benar-benar membutuhkan objek (dalam arti serangkaian bit yang mewakili nilai integral) dari jumlah bit tertentu, sebagian besar kompiler memiliki beberapa metode untuk menentukan itu; Tapi itu umumnya tidak portabel, bahkan antara kompiler yang dibuat oleh perusahaan ame tetapi untuk platform yang berbeda. Beberapa standar dan praktik (terutama limit.h dan sejenisnya) cukup umum sehingga sebagian besar penyusun akan memiliki dukungan untuk menentukan jenis yang paling cocok untuk rentang nilai tertentu, tetapi bukan jumlah bit yang digunakan. (Yaitu, jika Anda tahu Anda perlu menyimpan nilai antara 0 dan 127, Anda dapat menentukan bahwa kompiler Anda mendukung tipe 8-bit "int8" yang akan cukup besar untuk menampung rentang penuh yang diinginkan, tetapi bukan sesuatu seperti Tipe "int7" yang akan cocok dengan 7-bit.)

Catatan: Banyak paket sumber Un * x menggunakan skrip "./configure" yang akan menyelidiki kapabilitas kompiler / sistem dan menghasilkan Makefile dan config.h yang sesuai. Anda dapat memeriksa beberapa skrip ini untuk melihat cara kerjanya dan bagaimana mereka menyelidiki kemampuan comiler / sistem, dan mengikuti jejak mereka.

CM
sumber
1

Jika Anda tertarik dengan solusi C ++ murni, saya menggunakan template dan hanya kode standar C ++ untuk mendefinisikan tipe pada waktu kompilasi berdasarkan pada ukuran bitnya. Ini membuat solusi portable di kompiler.

Gagasan di baliknya sangat sederhana: Buat daftar yang berisi tipe char, int, pendek, panjang, panjang (versi yang ditandatangani dan tidak ditandatangani) dan pindai daftar dan dengan menggunakan template numeric_limits pilih jenis dengan ukuran yang diberikan.

Termasuk tajuk ini, Anda mendapatkan 8 tipe stdtype :: int8, stdtype :: int16, stdtype :: int32, stdtype :: int64, stdtype :: uint8, stdtype :: uint16, stdtype :: uint32, stdtype :: uint64.

Jika beberapa jenis tidak dapat diwakili itu akan dievaluasi ke stdtype :: null_type juga dideklarasikan di header itu.

KODE DI BAWAH INI DIBERIKAN TANPA GARANSI, TOLONG GANDA CEK.
AKU BARU DI METAPROGRAMMING JUGA, MERASA GRATIS UNTUK MENGEDIT DAN MEMPERBAIKI KODE INI.
Diuji dengan DevC ++ (jadi versi gcc sekitar 3,5)

#include <limits>

namespace stdtype
{
    using namespace std;


    /*
     * THIS IS THE CLASS USED TO SEMANTICALLY SPECIFY A NULL TYPE.
     * YOU CAN USE WHATEVER YOU WANT AND EVEN DRIVE A COMPILE ERROR IF IT IS 
     * DECLARED/USED.
     *
     * PLEASE NOTE that C++ std define sizeof of an empty class to be 1.
     */
    class null_type{};

    /*
     *  Template for creating lists of types
     *
     *  T is type to hold
     *  S is the next type_list<T,S> type
     *
     *  Example:
     *   Creating a list with type int and char: 
     *      typedef type_list<int, type_list<char> > test;
     *      test::value         //int
     *      test::next::value   //char
     */
    template <typename T, typename S> struct type_list
    {
        typedef T value;
        typedef S next;         

    };




    /*
     * Declaration of template struct for selecting a type from the list
     */
    template <typename list, int b, int ctl> struct select_type;


    /*
     * Find a type with specified "b" bit in list "list"
     *
     * 
     */
    template <typename list, int b> struct find_type
    {   
        private:
            //Handy name for the type at the head of the list
            typedef typename list::value cur_type;

            //Number of bits of the type at the head
            //CHANGE THIS (compile time) exp TO USE ANOTHER TYPE LEN COMPUTING
            enum {cur_type_bits = numeric_limits<cur_type>::digits};

        public:
            //Select the type at the head if b == cur_type_bits else
            //select_type call find_type with list::next
            typedef  typename select_type<list, b, cur_type_bits>::type type;
    };

    /*
     * This is the specialization for empty list, return the null_type
     * OVVERRIDE this struct to ADD CUSTOM BEHAVIOR for the TYPE NOT FOUND case
     * (ie search for type with 17 bits on common archs)
     */
    template <int b> struct find_type<null_type, b>
    {   
        typedef null_type type;

    };


    /*
     * Primary template for selecting the type at the head of the list if
     * it matches the requested bits (b == ctl)
     *
     * If b == ctl the partial specified templated is evaluated so here we have
     * b != ctl. We call find_type on the next element of the list
     */
    template <typename list, int b, int ctl> struct select_type
    {   
            typedef  typename find_type<typename list::next, b>::type type; 
    };

    /*
     * This partial specified templated is used to select top type of a list
     * it is called by find_type with the list of value (consumed at each call)
     * the bits requested (b) and the current type (top type) length in bits
     *
     * We specialice the b == ctl case
     */
    template <typename list, int b> struct select_type<list, b, b>
    {
            typedef typename list::value type;
    };


    /*
     * These are the types list, to avoid possible ambiguity (some weird archs)
     * we kept signed and unsigned separated
     */

    #define UNSIGNED_TYPES type_list<unsigned char,         \
        type_list<unsigned short,                           \
        type_list<unsigned int,                             \
        type_list<unsigned long,                            \
        type_list<unsigned long long, null_type> > > > >

    #define SIGNED_TYPES type_list<signed char,         \
        type_list<signed short,                         \
        type_list<signed int,                           \
        type_list<signed long,                          \
        type_list<signed long long, null_type> > > > >



    /*
     * These are acutally typedef used in programs.
     * 
     * Nomenclature is [u]intN where u if present means unsigned, N is the 
     * number of bits in the integer
     *
     * find_type is used simply by giving first a type_list then the number of 
     * bits to search for.
     *
     * NB. Each type in the type list must had specified the template 
     * numeric_limits as it is used to compute the type len in (binary) digit.
     */
    typedef find_type<UNSIGNED_TYPES, 8>::type  uint8;
    typedef find_type<UNSIGNED_TYPES, 16>::type uint16;
    typedef find_type<UNSIGNED_TYPES, 32>::type uint32;
    typedef find_type<UNSIGNED_TYPES, 64>::type uint64;

    typedef find_type<SIGNED_TYPES, 7>::type    int8;
    typedef find_type<SIGNED_TYPES, 15>::type   int16;
    typedef find_type<SIGNED_TYPES, 31>::type   int32;
    typedef find_type<SIGNED_TYPES, 63>::type   int64;

}
pengguna781847
sumber
0
unsigned char bits = sizeof(X) << 3;

di mana Xadalah char, int, longdll .. akan memberikan ukuran Xdalam bit.

pengguna3154672
sumber
1
char tidak selalu 8 bit, jadi ekspresi Anda tidak akan berfungsi pada arsitektur dengan char non-8-bit . Hanya sizeof(type)*CHAR_BITmemegang
phuclv
Bahkan jika CHAR_BITdijamin menjadi 8 bit, << 3hanyalah cara yang membingungkan untuk menulis * 8atau * CHAR_BIT.
Keith Thompson
0

Dari Alex B Standar C ++ tidak menentukan ukuran tipe integral dalam byte, tetapi menentukan rentang minimum yang harus mereka pegang. Anda dapat menyimpulkan ukuran minimum dalam bit dari rentang yang diperlukan. Anda dapat menyimpulkan ukuran minimum dalam byte dari itu dan nilai makro CHAR_BIT yang mendefinisikan jumlah bit dalam byte (di semua kecuali platform yang paling tidak jelas itu 8, dan tidak bisa kurang dari 8).

Satu kendala tambahan untuk char adalah ukurannya selalu 1 byte, atau CHAR_BIT bit (karena itu namanya).

Kisaran minimum yang disyaratkan oleh standar (halaman 22) adalah:

dan Kisaran Tipe Data di MSDN:

menandatangani char: -127 hingga 127 (catatan, bukan -128 hingga 127; ini mengakomodasi platform 1's-pelengkap) char tanpa tanda tangan: 0 hingga 255 char "polos": -127 hingga 127 atau 0 hingga 255 (tergantung pada penandatanganan char default) ditandatangani pendek: -32767 hingga 32767 unsigned pendek: 0 hingga 65535 ditandatangani int: -32767 hingga 32767 int ditandatangani: 0 hingga 65535 ditandatangani panjang: -2147483647 hingga 2147483647 unsigned panjang: 0 hingga 4294967295 ditandatangani lama: -9223372036854775807 0 hingga 18446744073709551615 Implementasi C ++ (atau C) dapat menentukan ukuran suatu tipe dalam byte sizeof (tipe) dengan nilai apa saja, selama

ekspresi sizeof (tipe) * CHAR_BIT mengevaluasi jumlah bit yang cukup untuk memuat rentang yang diperlukan, dan urutan tipe masih valid (mis. sizeof (int) <= sizeof (panjang)). Rentang implementasi spesifik yang sebenarnya dapat ditemukan di header di C, atau di C ++ (atau bahkan lebih baik, templated std :: numeric_limits di header).

Misalnya, ini adalah bagaimana Anda akan menemukan rentang maksimum untuk int:

C:

#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;

C ++:

#include <limits>
const int min_int = std::numeric_limits<int>::min();
const int max_int = std::numeric_limits<int>::max();

Ini benar, namun, Anda juga benar dalam mengatakan bahwa: char: 1 byte pendek: 2 byte int: 4 byte panjang: 4 byte float: 4 byte ganda: 8 byte

Karena arsitektur 32 bit masih merupakan standar dan paling banyak digunakan, dan mereka telah mempertahankan ukuran standar ini sejak pra-32 bit saat memori kurang tersedia, dan untuk kompatibilitas dan standardisasi mundur tetap sama. Bahkan sistem 64 bit cenderung menggunakan ini dan memiliki perluasan / modifikasi. Silakan rujuk ini untuk informasi lebih lanjut:

http://en.cppreference.com/w/cpp/language/types

JCoder
sumber
0

Saya perhatikan bahwa semua jawaban lain di sini telah berfokus hampir secara eksklusif pada tipe integral, sementara si penanya juga bertanya tentang poin-poin mengambang.

Saya tidak berpikir standar C ++ memerlukannya, tetapi kompiler untuk platform paling umum hari ini umumnya mengikuti standar IEEE754 untuk angka floating-point mereka. Standar ini menetapkan empat jenis biner floating-point (serta beberapa format BCD, yang belum pernah saya lihat dukungannya dalam kompiler C ++):

  • Setengah presisi (binary16) - signifikan 11-bit, rentang eksponen -14 hingga 15
  • Presisi tunggal (binary32) - Signifikan 24-bit, rentang eksponen -126 hingga 127
  • Presisi ganda (binary64) - 53-bit signifikan, kisaran eksponen -1022 hingga 1023
  • Presisi quadruple (binary128) - 113-bit signifikan, kisaran eksponen -16382 hingga 16383

Bagaimana peta ini ke tipe C ++, lalu? Umumnya floatmenggunakan presisi tunggal; demikian sizeof(float) = 4,. Kemudian doublegunakan presisi ganda (saya percaya itu sumber namanya double), danlong double mungkin presisi ganda atau empat kali lipat (itu empat kali lipat pada sistem saya, tetapi pada sistem 32-bit mungkin ganda). Saya tidak tahu ada kompiler yang menawarkan floating-point setengah presisi.

Singkatnya, ini adalah yang biasa:

  • sizeof(float) = 4
  • sizeof(double) = 8
  • sizeof(long double) = 8 atau 16
celticminstrel
sumber
Lucu bahwa saya sampai pada pertanyaan ini sebagai bagian dari bertanya-tanya mengapa Jeff menggunakan lebih banyak byte daripada yang dia butuhkan.
Aniruddha Varma
-2

Anda dapat menggunakan variabel yang disediakan oleh perpustakaan seperti OpenGL , Qt , dll.

Sebagai contoh, Qt menyediakan qint8 (dijamin 8-bit pada semua platform yang didukung oleh Qt), qint16, qint32, qint64, quint8, quint16, quint32, quint64, dll.

Lawand
sumber
1
Tidak menjawab pertanyaan
EvilTeach
-8

Pada mesin 64-bit:

int: 4
long: 8
long long: 8
void*: 8
size_t: 8
pengguna2826084
sumber
2
Pada beberapa mesin 64 bit intadalah 8 byte, tetapi yang lain tidak dijamin. Tidak ada yang mengatakan bahwa charseharusnya hanya 8 bit. Itu diizinkan untuk memiliki sizeof(void*)==4meskipun itu 64 bit.
meroket
-10

Ada empat jenis bilangan bulat berdasarkan ukuran:

  • integer pendek: 2 byte
  • integer panjang: 4 byte
  • bilangan bulat panjang: 8 byte
  • integer: tergantung pada kompiler (16 bit, 32 bit, atau 64 bit)
ricky
sumber
11
Salah, semuanya tergantung dari arsitektur, dengan rentang minimum yang dijelaskan dalam salah satu jawaban lainnya. Tidak ada yang menghentikan implementasi untuk dimiliki short, intdan longsemua integer 32 bit.
Matteo Italia
Anda bahkan belum menggunakan nama yang benar untuk jenisnya. Nama-nama menggunakan kata kunci int, bukan kata "integer".
Keith Thompson