Usulan C++: byte harus tepat 8 bit
(open-std.org)- P3477R0 adalah usulan perubahan standar agar ukuran byte di C++ tidak lagi bergantung pada nilai
CHAR_BITyang ditentukan implementasi, melainkan ditetapkan tepat 8 bit - Platform modern pada dasarnya sudah berkonvergensi dengan asumsi byte 8 bit, dan GCC, LLVM, serta MSVC juga menetapkan nilai bawaan atau makro terkait ke 8
- POSIX sejak POSIX.1-2001 mewajibkan
CHAR_BIT == 8, dan arah adopsi representasi bilangan bulat two’s complement di C++20 dan C23 juga sejalan dengan itu - Dukungan untuk byte non-8-bit menyisakan pengecualian kecil di seluruh bahasa, pustaka, dan toolchain, serta menimbulkan beban kasus tepi yang dianggap tidak selaras dengan penggunaan C++ modern di dunia nyata
- Arsitektur pengecualian seperti PDP-10 atau beberapa DSP memang ada, tetapi pertanyaan utamanya adalah apakah standar C++ baru harus terus mempertahankan kompleksitas demi target tersebut
Tujuan perubahan P3477R0
- C++ mewarisi makro
CHAR_BITdari C, dan saat ini nilainya merupakan nilai yang ditentukan implementasi untuk menyatakan jumlah bit dalam satu byte - P3477R0 mengusulkan agar standar C++ secara resmi mewajibkan byte berukuran 8 bit
- Pada masa awal komputasi, fleksibilitas untuk mengizinkan berbagai ukuran byte memang bermakna, tetapi penilaiannya adalah bahwa hampir semua perangkat keras modern kini telah berkonvergensi pada asumsi byte 8 bit
Kondisi kompilator dan platform saat ini
- Kompilator utama pada dasarnya sudah memperlakukan byte 8 bit sebagai kenyataan bawaan
- Dari contoh dukungan lama di GCC,
dsp16xxdihapus pada 2004 dan1750adihapus pada 2002 - Dari penelusuran web memang terlihat beberapa port GCC di luar upstream dengan
BITS_PER_UNITbukan 8, tetapi dinilai tidak tampak relevan dengan C++ modern
Arah POSIX dan representasi bilangan bulat
- POSIX sejak POSIX.1-2001 mewajibkan syarat berikut
- byte harus tepat 8 bit
CHAR_BITharus8SCHAR_MAXharus127,SCHAR_MINharus-128,UCHAR_MAXharus255
- POSIX menjelaskan bahwa penambahan
int8_tmengharuskanchar8 bit dan aritmetika two’s complement - C++20 setelah P0907r4 hanya mendukung representasi penyimpanan two’s complement, dan C23 mengikuti arah yang sama
- Contoh sistem operasi yang saat ini patuh POSIX yang dicantumkan meliputi AIX, HP-UX, INTEGRITY, macOS, OpenServer, UnixWare, VxWorks, dan vz/OS
Biaya yang ditinggalkan byte non-8-bit
- Perangkat lunak untuk byte 8 bit dan perangkat lunak untuk byte non-8-bit tidak saling kompatibel, dan kode C/C++ untuk target byte non-8-bit pada praktiknya dianggap lebih mirip dialek yang tidak kompatibel dari C dan C++
- Dukungan untuk arsitektur byte non-8-bit menyisakan kompleksitas kecil namun tidak perlu di berbagai bagian bahasa dan pustaka
- Kompilator dan toolchain harus terus menanggung kasus tepi yang tidak mencerminkan penggunaan modern
- Programmer baru mudah bingung karena karakteristik eksotis C++ semacam ini
- Sebagian programmer berpengalaman juga dianggap menghabiskan waktu pada “portabilitas” untuk platform yang praktis tidak ada
Arsitektur pengecualian dan kompromi
- Usulan ini juga mengakui bahwa prosesor dengan byte non-8-bit masih ada
- Pertanyaan intinya adalah apakah prosesor semacam itu masih relevan dengan C++ modern, dan apakah penggunanya benar-benar akan memakai versi C++ baru
- Sebagai kompromi, diajukan juga opsi untuk mewajibkan
CHAR_BIT % 8 == 0, tetapi ini hanya bermakna jika komite memang ingin terus mendukung DSP atau prosesor lain yangCHAR_BIT-nya bukan 8 namun merupakan kelipatan 8 - PDP-10 termasuk dalam pembahasan, tetapi dibedakan bahwa PDP-11 menggunakan byte 8 bit
- Sebagian DSP memperlakukan word 24 bit atau 32 bit seperti “byte”, dan arsitektur seperti ini pernah masuk akal pada masa ketika ukuran word beragam dan konsep byte belum distandardisasi
Arah perubahan redaksi standar
- Definisi byte di
intro.memoryakan diubah untuk menegaskan bahwa byte, sebagai unit penyimpanan dasar dalam model memori C++, adalah 8 bit - Di
climits, diusulkan perubahan redaksi agarCHAR_BITbernilai8 - Di
cstdint, karena byte adalah 8 bit, tipe bilangan bulat dengan lebar tetap sepertiint8_t,uint8_t, dan makro terkait tidak lagi bersifat opsional - Untuk tipe yang memakai
_N_, jikaNbukan8,16,32, atau64, statusnya tetap opsional - Perubahan ini juga mencakup penghapusan 4 klausul mandates terkait
CHAR_BIT == 8di dalamlocalization
Hubungan dengan standar C
- Usulan ini meninjau apakah C++ masih perlu terus relevan bagi arsitektur byte non-8-bit
- Komite C bisa saja mencapai kesimpulan berbeda untuk bahasa C
- Walaupun idealnya kedua komite selaras, usulan ini menempatkan peran kelompok penghubung WG14 dan SG22 untuk memberikan informasi kepada WG21
1 komentar
Pendapat di Hacker News
Dalam seri JF “Bukankah kita bisa mengakui bahwa komputer nyata memang semuanya bekerja seperti ini?”, sudah ada bagian bilangan bulat bertanda adalah komplemen dua: "Signed Integers are Two’s Complement"
Namun kalau begitu, kode klasik kernel Linux ini bisa jadi usang: https://github.com/torvalds/linux/blob/master/include/math-emu/double.h#L29
Saat magang pada 1986, saya menulis kode C di BBN C/70 yang memakai byte 10-bit; itu pengalaman mengerikan, dan keberadaan mesin seperti itu sejak awal adalah semacam kecelakaan kosmik dalam arti buruk
Mesin itu memakai word 36-bit dan byte 7-bit, dan saat byte diisikan ke word masih ada bit yang tersisa. Lalu saya diberi tugas membaca tape berisi data biner dalam format 8-bit, jadi kacau sekali
Namun C 10-bit adalah cerita yang berbeda
D membuat kemajuan besar dengan menetapkan hal-hal berikut: byte adalah 8-bit, short 16-bit, int 32-bit, long 64-bit, aritmetika adalah komplemen dua, dan floating point adalah floating point IEEE
Banyak sekali waktu yang dulu dihabiskan untuk mencoba mengabstraksikan hal-hal seperti ini lalu akhirnya salah pun terselamatkan, dan jutaan orang merasa lega. Set karakternya juga Unicode, bukan EBCDIC atau RADIX-50
u8/i8,u16/i16,u32/i32,u64/i64, dan aritmetikanya juga dipilih secara eksplisitOverflow pada
+adalah perilaku keliru sehingga dihentikan pada debug dan releasesafe,+%adalah wrapping komplemen dua, dan+|adalah aritmetika saturasi.@addWithOverflow()memberi tuple berisi tipe asli danu1, sedangkanstd.math.add()mengembalikan error saat overflow.f16,f32,f64,f80,f128juga masing-masing adalah tipe floating point IEEE dengan panjang bit terkait. Berapa panjang byte tidak penting; kalau mesinnya memakai byte 12-bit, tinggal gunakanu12dani12u8,i32jauh lebih baik dalam segala halunsignedditangani keliru, tetapi standardisasi jumlah bit tipe primitif dilakukan dengan tepatbyte = 8 bits,short = 16,int = 32,long = 64,float = 32 bit IEEE,double = 64 bit IEEEMasih ada orang yang harus berurusan dengan DSP: https://thephd.dev/conformance-should-mean-something-fputc-and-freestanding#we-cannot-program-on--vibes-
Secara pribadi, saya sedang mendokumentasikan, sekadar iseng, konsol fantasi 12-bit yang belum diimplementasikan dengan slogan “50% lebih banyak bit per byte dibanding pesaing!”, dan juga memasukkan ciptaan seperti “UTF-12”
Sudah bertahun-tahun saya bertanya tetapi belum mendapat jawaban positif; yang disebut hanya TI, jadi saya menambahkan informasinya ke draf pembaruan: https://isocpp.org/files/papers/D3477R1.html
CHAR_BIT=32di versi seperti C++30, saya tidak akan menangis sambil protesSaya penasaran apakah C++ bisa membuang atau menyederhanakan sesuatu
Ini pertanyaan yang tulus, dan saya tidak mengikutinya secara mendetail. Saya dengar
rand()sudah rusak dan tidak bisa diperbaiki, tetapi setahu saya terakhir bahkan belum dijadwalkan untuk deprecated. Proposal ini terlihat seperti ujian: “bisakah kita juga menghapus dukungan untuk solusi atas masalah yang secara harfiah tidak dialami siapa pun?”C dan C++ modern membuang itu dan mewajibkan komplemen dua. Di sini pembedaan “as if” juga secara praktis tidak penting, dan karena bisa diterapkan ke
CHAR_BITdengan cara yang sama, jelas ada preseden untuk perubahan semacam inirandjuga sudah dibuat deprecated serta disediakan alternatifnyaSelain itu ada
p2809 Trivial infinite loops are not Undefined Behavior,p1152 Deprecating volatile,p0907 Signed Integers are Two's Complement,p2723 Zero-initialize objects of automatic storage duration, danp2186 Removing Garbage Collection Support. Jadi perubahan memang mungkin dilakukanSpesifikasi exception juga dihapus, meski ada orang yang ingin menghidupkannya kembali untuk exception bertipe nilai.
auto_ptrjuga dihapus karena desainnya rusak. Namun dari sisi penyederhanaan, ini tidak terlalu membaik karena cara lama tetap perlu diketahuiSeolah-olah C++ membutuhkan simbol baru yang dapat merujuk byte 8-bit secara stabil tanpa merusak kompatibilitas. Misalnya, bisa dibuat
unsigned byte8,signed byte8komplemen dua, danbyte8dengan perilaku tanda yang tidak didefinisikan. Lalu, sebagai lelucon, untuk akuntan ditambahkanunsigned decimal byte8dansigned decimal byte8yang membatasi rentang nilai ke 0~10 dan -10~+10; untuk akuntan yang bahkan memperhitungkan biaya per byte adacentimal byte8dengan 0~100 dan -100~+100; tipe yang kira-kira cukup untuk fieldagedi database; dan tentu sajafloat byte8rand()dianggap rusak. Ia menghasilkan nilai yang tampak acak, dan memang itulah tujuannyaTentu saja ia tidak menghasilkan bilangan acak yang aman secara kriptografis, dan fungsi setara di bahasa lain juga begitu. Kalau yang dibutuhkan adalah integer yang cukup acak dan cepat dihitung,
rand()bekerja cukup baikTerima kasih atas ketertarikannya pada proposal ini; berdasarkan umpan balik sejauh ini, saya membuat draf pembaruan: https://isocpp.org/files/papers/D3477R1.html
Terutama kalimat ini berkesan: “Masalahnya bukan apakah masih ada arsitektur yang bytenya bukan 8 bit. Ada! Masalahnya adalah apakah mereka peduli pada C++ modern, dan apakah C++ modern peduli pada mereka”
Saya punya perasaan campur aduk soal proposal ini. Di satu sisi, ini jelas benar, dan tidak ada penggunaan bermakna untuk
CHAR_BITyang bukan 8Di sisi lain, rasanya seperti menyerah pada pandangan dunia yang adil, bahwa dunia harus masuk akal dan bisa ditalar hanya dengan model pribadi yang terlalu disederhanakan tentang isi komputer. Pendekatan seperti ini bisa membawa kita cukup jauh, tetapi pada akhirnya buntu; pada titik terakhir, kita harus mengakui bahwa kita tidak tahu apa-apa dan bahwa argumen formal bahwa program yang kita susun benar hanya berlaku jika dokumentasinya benar. Ini lompatan intelektual yang besar, dan bagi saya pribadi, makin lama saya tidak dipaksa mengakuinya, makin sulit melompatinya nanti. Meski begitu, proyek elektronika fisik tampaknya sedang populer di kalangan pemula sekarang, jadi semoga standar barunya bukan “baca dokumentasinya”, melainkan “baca datasheet sialan itu”
autoconf, saya tetap melihatnya memeriksa jumlah bit dalam satu byte dan menyimpannya diconfig.h. Seolah-olah ada orang yang benar-benar berencana bertindak berdasarkan nilai ituPerlu ada cara untuk memeriksa seluruh kode lama selama proses kompilasi untuk memastikan apakah makro ini sudah digunakan. Perubahan yang memecah kompatibilitas seperti ini juga berisiko membelah bahasa. Tingkat kesulitan untuk menguji apakah codebase lama memakai makro
CHAR_BITdan apakah bisa diperbarui ke compiler baru juga belum jelas. Pertanyaan lain juga muncul, seperti library apa yang akan dianggap rusak, dan apakah masalah juga timbul saat berinteraksi dengan kode lain yang dikompilasi menggunakanCHAR_BIT. Saya setuju ini terasa tidak intuitif, tetapi sebaiknya buat dulu alat konversi dan tunjukkan bahwa peralihan ini aman bahkan pada kasus ekstrem, baru kemudian beralihSaya suka karena ini proposal yang sama sekali sulit dibantah tetapi juga luar biasa pedas
Memaksa
int8_t == char == 8 bitssepenuhnya oke, tetapi saya tidak yakin soal menyebarkan kesalahpahaman bahwa byte adalah 8 bitByte 8-bit disebut oktet (octet). Pada saat yang sama, sejak C++17
bytejuga sudah menjadi semacam “alias” untukchar: https://en.cppreference.com/w/cpp/types/byteSelama 45 tahun berikutnya saya belum pernah melihat “byte” dipakai dengan arti lain, jadi kalau ada definisi “byte” yang bukan 8 bit, saya perlu sumbernya
Ini bukan pernyataan deskriptif, melainkan pernyataan normatif
int8 == signed charstd::cout << (int8_t)32 << std::endl;seharusnya tentu saja mencetak 32Tidak berkaitan dengan C++, tetapi saya cukup menyukai ide mikrokomputer retro dengan byte 6-bit. Jadi 24 bit menjadi satu word
Mikrokomputer biasanya menangani sedikit objek dan lebih menyukai array daripada pointer, sehingga bisa menghemat memori. VGA memakai 6 bit per warna, alfabet yang masih terbaca bisa dibuat dengan matriks bit 6x4, bahasa dasar seperti LISP atau Forth juga bisa dimasukkan ke alfabet 6-bit, dan System/360 awalnya hanya memakai alamat 24-bit. Memori 12 MiB dengan unit 6-bit yang dapat dialamati secara independen seharusnya cukup untuk siapa pun. Kalau kurang, FAT-12 bisa diperluas secara alami menjadi FAT-24, atau gunakan pointer 48-bit yang sama bergunanya dengan pointer 64-bit