Sesekali, seseorang di SO menunjukkan bahwa char
(alias 'byte') belum tentu 8 bit .
Tampaknya 8-bit char
hampir universal. Saya akan berpikir bahwa untuk platform arus utama, perlu memiliki 8-bit char
untuk memastikan kelangsungan hidupnya di pasar.
Baik sekarang dan secara historis, platform apa yang menggunakan char
yang bukan 8 bit, dan mengapa mereka berbeda dari 8 bit "normal"?
Saat menulis kode, dan memikirkan tentang dukungan lintas platform (misalnya untuk pustaka penggunaan umum), pertimbangan macam apa yang layak diberikan untuk platform dengan non-8-bit char
?
Di masa lalu saya telah menemukan beberapa Perangkat Analog DSP yang char
16 bit. DSP adalah sedikit arsitektur khusus yang saya kira. (Kemudian lagi, pada saat assembler dengan kode tangan dengan mudah mengalahkan apa yang dapat dilakukan oleh kompiler C yang tersedia, jadi saya tidak benar-benar mendapatkan banyak pengalaman dengan C pada platform itu.)
sumber
Jawaban:
char
juga 16 bit di Texas Instruments C54x DSP, yang muncul misalnya di OMAP2. Ada DSP lain di luar sana dengan 16 dan 32 bitchar
. Saya rasa saya pernah mendengar tentang DSP 24-bit, tetapi saya tidak ingat apa, jadi mungkin saya membayangkannya.Pertimbangan lain adalah mandat POSIX
CHAR_BIT == 8
. Jadi jika Anda menggunakan POSIX, Anda dapat mengasumsikannya. Jika kemudian seseorang perlu mem-port kode Anda ke implementasi POSIX yang hampir selesai, yang kebetulan memiliki fungsi yang Anda gunakan tetapi ukurannya berbedachar
, itu adalah nasib buruk mereka.Namun secara umum, menurut saya, mengatasi masalah ini hampir selalu lebih mudah daripada memikirkannya. Ketik saja
CHAR_BIT
. Jika Anda menginginkan tipe 8 bit yang tepat, gunakanint8_t
. Kode Anda akan gagal untuk dikompilasi pada implementasi yang tidak menyediakannya, alih-alih diam-diam menggunakan ukuran yang tidak Anda harapkan. Paling tidak, jika saya menemukan kasus di mana saya memiliki alasan kuat untuk mengasumsikannya, maka saya akan menegaskannya.sumber
assert()
(jika itu yang Anda maksud), saya akan menggunakan#if CHAR_BIT != 8
...#error "I require CHAR_BIT == 8"
...#endif
static_assert()
?Ini tidak terlalu berarti bahwa "layak memberikan pertimbangan" pada sesuatu karena itu dimainkan sesuai aturan. Dalam C ++, misalnya, standar mengatakan semua byte akan memiliki "setidaknya" 8 bit. Jika kode Anda mengasumsikan bahwa byte memiliki tepat 8 bit, Anda melanggar standar.
Ini mungkin tampak konyol sekarang - " tentu saja semua byte memiliki 8 bit!", Saya mendengar Anda berkata. Tetapi banyak orang yang sangat pintar mengandalkan asumsi yang bukan jaminan, dan kemudian semuanya rusak. Sejarah penuh dengan contoh-contoh seperti itu.
Misalnya, sebagian besar pengembang awal 90-an berasumsi bahwa penundaan waktu CPU tanpa operasi tertentu yang mengambil sejumlah siklus tetap akan memakan waktu jam yang tetap, karena sebagian besar CPU konsumen kira-kira memiliki daya yang setara. Sayangnya, komputer menjadi lebih cepat dengan sangat cepat. Hal ini melahirkan munculnya kotak-kotak dengan tombol "Turbo" - yang tujuannya, ironisnya, adalah untuk memperlambat komputer sehingga game yang menggunakan teknik penundaan waktu dapat dimainkan dengan kecepatan yang wajar.
Seorang pemberi komentar bertanya di bagian mana dalam standar dikatakan bahwa char harus memiliki setidaknya 8 bit. Ini di bagian 5.2.4.2.1 . Bagian ini mendefinisikan
CHAR_BIT
, jumlah bit dalam entitas beralamat terkecil, dan memiliki nilai default 8. Ia juga mengatakan:Jadi angka apa pun yang sama dengan 8 atau lebih tinggi cocok untuk diganti dengan implementasi ke
CHAR_BIT
.sumber
char
ada lebih dari 64 dari mereka tetapi kurang dari 128 sehingga 7 bit akan cukup.Mesin dengan arsitektur 36-bit memiliki byte 9-bit. Menurut Wikipedia, mesin dengan arsitektur 36-bit meliputi:
sumber
Beberapa yang saya sadari:
sumber
char
tipe ini sama sekali? Saya tahu bahwa pustaka sistem hanya mendukung versi lebar dari fungsi yang mengambil string, dan bahwa setidaknya beberapa versi WinCE menghapus fungsi string ANSI seperti strlen, untuk menghentikan Anda melakukan penanganan string char. Tetapi apakah itu benar-benar tidak memiliki tipe karakter sama sekali? Apa itusizeof(TCHAR)
? Jenis apa yang dikembalikan malloc? Bagaimanabyte
tipe Java diimplementasikan?Tidak ada yang namanya kode yang sepenuhnya portabel. :-)
Ya, mungkin ada berbagai ukuran byte / karakter. Ya, mungkin ada implementasi C / C ++ untuk platform dengan nilai
CHAR_BIT
danUCHAR_MAX
. Ya, terkadang dimungkinkan untuk menulis kode yang tidak bergantung pada ukuran karakter.Namun, hampir semua kode nyata tidak berdiri sendiri. Misalnya, Anda mungkin menulis kode yang mengirim pesan biner ke jaringan (protokol tidak penting). Anda dapat menentukan struktur yang berisi bidang yang diperlukan. Daripada Anda harus membuat serial itu. Hanya menyalin biner struktur ke buffer keluaran tidak portabel: umumnya Anda tidak tahu urutan byte untuk platform, atau penyelarasan anggota struktur, jadi struktur hanya menyimpan data, tetapi tidak menjelaskan cara data harus berseri .
Baik. Anda dapat melakukan transformasi urutan byte dan memindahkan anggota struktur (misalnya
uint32_t
atau serupa) menggunakanmemcpy
ke buffer. Kenapamemcpy
? Karena ada banyak platform yang tidak memungkinkan untuk menulis 32-bit (16-bit, 64-bit - tidak ada perbedaan) ketika alamat target tidak disejajarkan dengan benar.Jadi, Anda telah melakukan banyak hal untuk mencapai portabilitas.
Dan sekarang pertanyaan terakhir. Kami memiliki penyangga. Data darinya dikirim ke jaringan TCP / IP. Jaringan tersebut mengasumsikan byte 8-bit. Pertanyaannya adalah: dari jenis apa buffer itu seharusnya? Jika karakter Anda 9-bit? Jika 16-bit? 24? Mungkin setiap karakter sesuai dengan satu byte 8-bit yang dikirim ke jaringan, dan hanya 8 bit yang digunakan? Atau mungkin beberapa byte jaringan dikemas menjadi karakter 24/16/9-bit? Itu pertanyaan, dan sulit dipercaya bahwa ada satu jawaban yang cocok untuk semua kasus. Banyak hal bergantung pada implementasi soket untuk platform target.
Jadi, apa yang saya bicarakan. Biasanya kode dapat dengan mudah dibuat portabel sampai batas tertentu . Sangat penting untuk melakukannya jika Anda berharap menggunakan kode pada platform yang berbeda. Namun, meningkatkan portabilitas di luar ukuran itu adalah hal yang membutuhkan banyak usaha dan sering kali memberi sedikit , karena kode sebenarnya hampir selalu bergantung pada kode lain (implementasi soket dalam contoh di atas). Saya yakin bahwa sekitar 90% dari kemampuan kode untuk bekerja pada platform dengan byte selain 8-bit hampir tidak berguna, karena menggunakan lingkungan yang terikat pada 8-bit. Cukup periksa ukuran byte dan lakukan pernyataan waktu kompilasi. Anda hampir pasti harus banyak menulis ulang untuk platform yang sangat tidak biasa.
Tetapi jika kode Anda sangat "mandiri" - mengapa tidak? Anda dapat menuliskannya dengan cara yang memungkinkan ukuran byte yang berbeda.
sumber
unsigned char
nilai, seharusnya tidak ada masalah portabilitas kecuali kode menggunakan trik aliasing daripada shift untuk mengonversi urutan oktet ke / dari jenis bilangan bulat yang lebih besar. Secara pribadi, saya pikir standar C harus mendefinisikan intrinsik untuk mengemas / membongkar bilangan bulat dari urutan jenis yang lebih pendek (paling biasanyachar
) menyimpan jumlah bit yang dijamin tersedia per item (8 perunsigned char
, 16 perunsigned short
, atau 32 perunsigned long
).Tampaknya Anda masih dapat membeli IM6100 (yaitu PDP-8 pada sebuah chip) dari gudang. Itu adalah arsitektur 12-bit.
sumber
Banyak chip DSP memiliki 16- atau 32-bit
char
. TI secara rutin membuat chip seperti itu misalnya .sumber
Dikutip dari http://en.wikipedia.org/wiki/Byte#History
Tidak yakin tentang bahasa lain.
http://en.wikipedia.org/wiki/IBM_7030_Stretch#Data_Formats
Mendefinisikan byte pada mesin itu menjadi panjang variabel
sumber
Keluarga DEC PDP-8 memiliki kata 12 bit meskipun Anda biasanya menggunakan ASCII 8 bit untuk keluaran (kebanyakan pada Teletype). Namun, ada juga kode karakter 6-BIT yang memungkinkan Anda untuk menyandikan 2 karakter dalam satu kata 12-bit.
sumber
Pertama, karakter Unicode lebih panjang dari 8-bit. Seperti yang disebutkan sebelumnya, spesifikasi C mendefinisikan tipe data dengan ukuran minimumnya. Gunakan
sizeof
dan nilai dilimits.h
jika Anda ingin menginterogasi tipe data Anda dan menemukan dengan tepat ukurannya untuk konfigurasi dan arsitektur Anda.Untuk alasan ini, saya mencoba untuk tetap menggunakan tipe data seperti
uint16_t
ketika saya membutuhkan tipe data dengan panjang bit tertentu.Edit: Maaf, saya awalnya salah membaca pertanyaan Anda.
Spesifikasi C mengatakan bahwa
char
objek "cukup besar untuk menyimpan setiap anggota set karakter eksekusi".limits.h
mencantumkan ukuran minimum 8 bit, tetapi definisi membiarkan ukuran maksimalchar
terbuka.Jadi, a
char
setidaknya sepanjang karakter terbesar dari set eksekusi arsitektur Anda (biasanya dibulatkan ke batas 8-bit terdekat). Jika arsitektur Anda memiliki opcode yang lebih panjang,char
ukuran Anda mungkin lebih panjang.Secara historis, opcode platform x86 adalah satu byte, jadi
char
awalnya nilai 8-bit. Platform x86 saat ini mendukung opcode yang lebih panjang dari satu byte, tetapichar
panjangnya tetap 8 bit karena itulah yang dikondisikan oleh programmer (dan volume besar kode x86 yang ada).Saat memikirkan tentang dukungan multi-platform, manfaatkan jenis yang ditentukan dalam
stdint.h
. Jika Anda menggunakan (misalnya) uint16_t, maka Anda dapat yakin bahwa nilai ini adalah nilai 16-bit unsigned pada arsitektur apapun, apakah itu nilai 16-bit berkorespondensi denganchar
,short
,int
, atau sesuatu yang lain. Sebagian besar kerja keras telah dilakukan oleh orang-orang yang menulis compiler / library standar Anda.Jika Anda perlu mengetahui ukuran pasti a
char
karena Anda melakukan manipulasi perangkat keras tingkat rendah yang memerlukannya, saya biasanya menggunakan tipe data yang cukup besar untuk menampungchar
di semua platform yang didukung (biasanya 16 bit sudah cukup) dan menjalankan nilai melaluiconvert_to_machine_char
rutinitas ketika saya membutuhkan representasi mesin yang tepat. Dengan begitu, kode khusus platform terbatas pada fungsi antarmuka dan sebagian besar waktu saya dapat menggunakan normaluint16_t
.sumber
angka ajaib terjadi misalnya saat menggeser;
sebagian besar dapat ditangani dengan mudah dengan menggunakan CHAR_BIT dan misalnya UCHAR_MAX, bukan 8 dan 255 (atau serupa).
semoga penerapan Anda mendefinisikannya :)
itu adalah masalah "umum" .....
masalah tidak langsung lainnya mengatakan Anda memiliki:
struct xyz { uchar baz; uchar blah; uchar buzz; }
ini mungkin "hanya" mengambil (kasus terbaik) 24 bit pada satu platform, tetapi mungkin mengambil misalnya 72 bit di tempat lain .....
jika setiap uchar memiliki "bit flags" dan setiap uchar hanya memiliki 2 bit "signifikan" atau flag yang saat ini Anda gunakan, dan Anda hanya mengaturnya menjadi 3 uchar untuk "kejelasan", maka itu mungkin relatif "lebih boros" misalnya pada platform dengan uchars 24-bit .....
tidak ada yang tidak bisa diselesaikan oleh bitfield, tetapi mereka memiliki hal-hal lain yang harus diperhatikan ....
dalam kasus ini, hanya satu enum yang mungkin menjadi cara untuk mendapatkan bilangan bulat berukuran "terkecil" yang sebenarnya Anda butuhkan ....
mungkin bukan contoh nyata, tetapi hal-hal seperti ini "menggigit" saya saat porting / bermain dengan beberapa kode .....
hanya fakta bahwa jika sebuah uchar adalah tiga kali lebih besar dari yang diharapkan "biasanya", 100 struktur seperti itu dapat menghabiskan banyak memori pada beberapa platform ..... di mana "biasanya" itu bukan masalah besar .... .
jadi hal-hal masih bisa "rusak" atau dalam hal ini "membuang banyak memori dengan sangat cepat" karena asumsi bahwa uchar "tidak terlalu boros" di satu platform, relatif terhadap RAM yang tersedia, daripada di platform lain ... ..
masalahnya mungkin lebih menonjol misalnya untuk int juga, atau jenis lain, misalnya Anda memiliki beberapa struktur yang membutuhkan 15 bit, jadi Anda menempelkannya di int, tetapi di beberapa platform lain int adalah 48 bit atau apa pun .... .
"biasanya" Anda dapat membaginya menjadi 2 uchar, tetapi misalnya dengan uchar 24-bit Anda hanya perlu satu .....
jadi enum mungkin menjadi solusi "umum" yang lebih baik ....
tergantung pada bagaimana Anda mengakses bit itu :)
jadi, mungkin ada "kekurangan desain" yang ada di belakang kepala mereka .... meskipun kodenya mungkin masih berfungsi / berjalan dengan baik terlepas dari ukuran uchar atau uint ...
ada hal-hal seperti ini yang harus diperhatikan, meskipun tidak ada "angka ajaib" di kode Anda ...
semoga ini masuk akal :)
sumber
enum
cenderung lebih kecil daripada jenis asli lainnya? Apakah Anda sadar ini default ke penyimpanan yang sama sepertiint
? "Anda memiliki beberapa struktur yang membutuhkan 15 bit, jadi Anda memasukkannya ke dalam int, tetapi di beberapa platform lain int adalah 48 bit atau apa pun ....." - jadi#include <cstdint>
dan jadikan ituint16_t
kesempatan terbaik untuk meminimalkan penggunaan bit . Saya benar-benar tidak yakin apa yang Anda pikir Anda katakan di antara semua elips itu.int dulu 16 bit (pdp11, dll.). Pergi ke arsitektur 32 bit itu sulit. Orang-orang menjadi lebih baik: Hampir tidak ada yang menganggap sebuah pointer akan muat lagi (Anda tidak benar?). Atau offset file, atau cap waktu, atau ...
Karakter 8 bit sudah agak dari anakronisme. Kita sudah membutuhkan 32 bit untuk menampung semua set karakter dunia.
sumber
char
agak aneh sekarang di zaman Unicode. Saya lebih peduli tentang unit 8-bit (oktet) saat berurusan dengan data biner, misalnya penyimpanan file, komunikasi jaringan.uint8_t
lebih bermanfaat.