C++ प्रस्ताव: byte अब ठीक 8-bit हो
(open-std.org)- P3477R0 C++ में byte के आकार को
CHAR_BITजैसे implementation-defined मान पर छोड़ने के बजाय उसे ठीक 8-bit पर तय करने वाला standard बदलाव प्रस्तावित करता है - आधुनिक platforms पहले ही 8-bit byte को आधार मानकर एकरूप हो चुके हैं, और GCC, LLVM, MSVC भी अपने संबंधित defaults या macros को 8 पर रखते हैं
- POSIX, POSIX.1-2001 से
CHAR_BIT == 8की मांग करता है, और C++20 तथा C23 में two's complement integer representation अपनाने की दिशा भी इसी ओर जाती है - non-8-bit byte support भाषा, library और toolchain में छोटे-छोटे exceptions छोड़ता है, और व्यावहारिक आधुनिक C++ उपयोग से मेल न खाने वाला edge case बोझ पैदा करता है
- PDP-10 या कुछ DSP जैसी अपवादात्मक architectures मौजूद हैं, लेकिन मुख्य प्रश्न यह है कि क्या नए C++ standard को अब भी उनके लिए यह जटिलता बनाए रखनी चाहिए
P3477R0 का बदलाव लक्ष्य
- C++ में C का
CHAR_BITmacro आता है, और फिलहाल यह मान byte में bits की संख्या बताने वाला implementation-defined value है - P3477R0 प्रस्ताव देता है कि C++ standard आधिकारिक रूप से byte को 8-bit होने की शर्त लगाए
- computing के शुरुआती दौर में अलग-अलग byte sizes की flexibility उपयोगी थी, लेकिन प्रस्ताव का आधार यह है कि आधुनिक hardware लगभग पूरी तरह 8-bit byte पर आकर स्थिर हो चुका है
compiler और platform की मौजूदा स्थिति
- प्रमुख compilers पहले से 8-bit byte को ही व्यावहारिक default मानते हैं
- GCC के पुराने support उदाहरणों में
dsp16xxको 2004 में, और1750aको 2002 में हटाया गया था - web search में कुछ external GCC ports दिखते हैं जहां
BITS_PER_UNIT8 नहीं है, लेकिन प्रस्ताव के अनुसार वे आधुनिक C++ से प्रासंगिक नहीं लगते
POSIX और integer representation की दिशा
- POSIX POSIX.1-2001 से निम्न शर्तें मांगता है
- byte ठीक 8-bit हो
CHAR_BIT8होSCHAR_MAX127,SCHAR_MIN-128,UCHAR_MAX255हों
- POSIX यह भी बताता है कि
int8_tजोड़ने के परिणामस्वरूप 8-bitcharऔर two's complement arithmetic की जरूरत पड़ती है - C++20, P0907r4 के बाद, सिर्फ two's complement storage को support करता है, और C23 भी इसी दिशा में चलता है
- वर्तमान POSIX-compliant operating systems के उदाहरण के रूप में AIX, HP-UX, INTEGRITY, macOS, OpenServer, UnixWare, VxWorks, vz/OS सूचीबद्ध हैं
non-8-bit byte से बची रहने वाली लागत
- 8-bit byte software और non-8-bit byte software एक-दूसरे के साथ compatible नहीं होते, और ऐसे target के लिए C/C++ code व्यावहारिक रूप से C और C++ की incompatible dialects जैसा हो जाता है
- non-8-bit byte architecture support भाषा और library के कई हिस्सों में छोटी लेकिन अनावश्यक complexity छोड़ता है
- compiler और toolchain को ऐसे edge cases का बोझ ढोना पड़ता है जो आधुनिक उपयोग को प्रतिबिंबित नहीं करते
- नए programmers C++ की इस तरह की असामान्य विशेषताओं से आसानी से भ्रमित हो सकते हैं
- प्रस्ताव का तर्क है कि कुछ अनुभवी programmers भी ऐसे platforms के लिए “portability” पर समय खर्च करते हैं जो वास्तव में मौजूद ही नहीं हैं
अपवाद architectures और समझौते का विकल्प
- प्रस्ताव यह मानता है कि non-8-bit byte processors अभी भी मौजूद हैं
- मुख्य सवाल यह है कि क्या ऐसे processors का modern C++ से कोई वास्तविक संबंध है, और क्या उनके users नए C++ versions अपनाएंगे
- समझौते के रूप में
CHAR_BIT % 8 == 0की शर्त का विकल्प भी रखा गया है, लेकिन इसका मतलब तभी है जब committeeCHAR_BITको 8 न होते हुए भी 8 के गुणज रखने वाले DSP या अन्य processors का support जारी रखना चाहे - PDP-10 चर्चा का विषय है, जबकि PDP-11 के बारे में अलग से बताया गया है कि वह 8-bit byte इस्तेमाल करता है
- कुछ DSP 24-bit या 32-bit words को “byte” जैसा मानते हैं; ऐसी architectures उस दौर में उचित थीं जब word sizes विविध थीं और byte की अवधारणा standard नहीं हुई थी
standard wording में बदलाव की दिशा
intro.memoryमें byte की परिभाषा बदलकर यह स्पष्ट करने का प्रस्ताव है कि C++ memory model की मूल storage unit byte 8-bit हैclimitsमेंCHAR_BITको8मानने की दिशा में wording बदलाव प्रस्तावित हैcstdintमें, क्योंकि byte 8-bit होगा,int8_t,uint8_tजैसे fixed-width integer types और संबंधित macros अब optional नहीं रहेंगे_N_का उपयोग करने वाले types में, जहांN8,16,32,64नहीं है, वहां उन्हें अब भी optional रखा जाएगाlocalizationके भीतरCHAR_BIT == 8से जुड़े 4 mandates clauses हटाने का बदलाव भी शामिल है
C standard के साथ संबंध
- प्रस्ताव यह जांचता है कि क्या C++ को non-8-bit byte architectures से जुड़ा रहना चाहिए
- C committee, C भाषा के लिए, किसी अलग निष्कर्ष पर पहुंच सकती है
- दोनों committees का aligned होना आदर्श होगा, लेकिन यह प्रस्ताव WG14 और SG22 liaison group से WG21 को जानकारी देने वाले ढांचे के रूप में रखा गया है
1 टिप्पणियां
Hacker News टिप्पणियां
JF की “क्या हम मान सकते हैं कि असली कंप्यूटर वैसे ही काम करते हैं?” सीरीज़ में पहले से signed integers 2's complement होते हैं वाला हिस्सा था: "Signed Integers are Two’s Complement"
हालांकि ऐसा करने से Linux kernel का यह क्लासिक कोड पुराना पड़ सकता है: https://github.com/torvalds/linux/blob/master/include/math-emu/double.h#L29
1986 में internship के दौरान मैंने 10-bit byte इस्तेमाल करने वाले BBN C/70 पर C code लिखा था; अनुभव भयानक था, और ऐसी machine का मौजूद होना ही नकारात्मक अर्थ में एक cosmic accident था
उसमें 36-bit word और 7-bit byte थे, और bytes को word में pack करने पर bits बच जाते थे। ऊपर से मुझे 8-bit format वाले binary data की tape पढ़ने का काम मिला था, तो पूरा बवाल हो गया
लेकिन 10-bit C की बात अलग है
D ने ये तय करके बड़ी छलांग लगाई: byte 8 bits का है, short 16 bits का, int 32 bits का, long 64 bits का, arithmetic 2's complement है, और floating-point IEEE floating-point है
इन चीज़ों को abstract करने की कोशिश में आखिरकार गलत साबित होने पर खर्च होने वाला बहुत सारा समय बचा, और लाखों लोगों ने राहत की सांस ली। character set भी EBCDIC या RADIX-50 नहीं, बल्कि Unicode था
u8/i8,u16/i16,u32/i32,u64/i64की तरह size explicit होता है, और arithmetic भी explicitly चुनी जाती है+में overflow गलत behavior है, इसलिए debug और releasesafe में abort होता है;+%2's complement wrapping है,+|saturating arithmetic है।@addWithOverflow()original type औरu1का tuple देता है, औरstd.math.add()overflow पर error लौटाता है।f16,f32,f64,f80,f128भी respectively उसी bit length के IEEE floating-point types हैं। byte length कितनी है, यह मायने नहीं रखता; अगर 12-bit byte machine हो तोu12औरi12इस्तेमाल कर लेंu8,i32, हर तरह से काफी बेहतर हैंunsignedको गलत तरीके से handle किया, लेकिन primitive type bit counts को standardize करने का काम सही कियाbyte = 8 bits,short = 16,int = 32,long = 64,float = 32 bit IEEE,double = 64 bit IEEEकुछ लोगों को अब भी DSP से निपटना पड़ता है: https://thephd.dev/conformance-should-mean-something-fputc-and-freestanding#we-cannot-program-on--vibes-
निजी तौर पर, मैं मज़ाक में एक unimplemented 12-bit fantasy console document कर रहा हूं, जिसका दावा है “competitors की तुलना में per byte 50% ज्यादा bits!”, और उसमें “UTF-12” जैसी inventions भी डाल रखी हैं
कई सालों से पूछ रहा हूं, लेकिन कोई positive जवाब नहीं मिला; जिनका ज़िक्र आया उनमें बस TI जैसा कुछ था, इसलिए updated draft में जानकारी जोड़ दी: https://isocpp.org/files/papers/D3477R1.html
CHAR_BIT=32support हटा दे, तो मैं रो-धोकर विरोध नहीं करूंगासोच रहा हूँ कि क्या C++ कभी कुछ हटा या सरल कर सकता है
यह ईमानदार सवाल है और मैंने बहुत बारीकी से follow नहीं किया है। सुना है कि
rand()टूटा हुआ है और उसे ठीक नहीं किया जा सकता, लेकिन आख़िरी बार जहाँ तक पता था, वह अभी deprecated होने वाला भी नहीं था। यह प्रस्ताव ऐसा test लगता है कि “क्या हम सचमुच ऐसी समस्या के solution का support भी हटा सकते हैं जिसका सामना शाब्दिक रूप से कोई नहीं करता?”आधुनिक C और C++ ने इसे छोड़कर 2's complement की मांग कर दी है। यहाँ “as if” वाला अंतर भी practically महत्वपूर्ण नहीं है, और इसे
CHAR_BITपर भी उसी तरह लागू किया जा सकता है, इसलिए ऐसी change का precedent साफ़ तौर पर मौजूद हैrandको भी deprecation के लिए चिह्नित किया गया है, साथ में alternative भी दिया गया हैइसके अलावा
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,p2186 Removing Garbage Collection Supportभी हैं। इसलिए बदलाव करना संभव हैexception specifications भी हटाए गए, हालांकि कुछ लोग value-type exceptions के लिए उन्हें वापस लाना चाहते हैं।
auto_ptrभी खराब design के कारण हटाया गया। हालांकि simplification के लिहाज़ से बहुत सुधार नहीं हुआ, क्योंकि पुराना तरीका अब भी जानना पड़ता हैबात कुछ ऐसी है कि compatibility तोड़े बिना 8-bit byte को भरोसेमंद तरीके से दर्शाने वाला नया C++ symbol चाहिए। जैसे
unsigned byte8, 2's complementsigned byte8, और ऐसाbyte8जिसका signed behavior defined न हो। accountants के लिए value range 0~10, -10~+10 तक सीमित करने वालेunsigned decimal byte8औरsigned decimal byte8, byte की cost तक गिनने वाले accountants के लिए 0~100, -100~+100 वालेcentimal byte8, database केagefield के लिए मोटे तौर पर पर्याप्त type, और ज़ाहिर हैfloat byte8भी जोड़ दें — यही मज़ाक हैrand()टूटा हुआ क्यों है। वह random जैसे दिखने वाले values बनाता है, और उसका मकसद यही हैयह cryptographically secure random numbers नहीं बनाता, यह तो स्वाभाविक है, और दूसरी languages के equivalent functions भी ऐसे ही हैं। जल्दी calculate होने वाले, ठीक-ठाक random integers चाहिए हों तो
rand()काफी अच्छी तरह काम करता हैप्रस्ताव में दिलचस्पी लेने के लिए धन्यवाद, और अब तक मिले feedback के आधार पर updated draft बनाया है: https://isocpp.org/files/papers/D3477R1.html
खासकर यह वाक्य impressive है: “समस्या यह नहीं है कि क्या ऐसे architectures अब भी मौजूद हैं जहाँ byte 8-bit नहीं है। मौजूद हैं! समस्या यह है कि क्या वे modern C++ की परवाह करते हैं, और क्या modern C++ उनकी परवाह करता है”
इस प्रस्ताव को लेकर mixed feelings हैं। एक तरफ़ यह साफ़ तौर पर सही है, और
CHAR_BITका 8 न होना meaningful use cases में काम का नहीं हैदूसरी तरफ़ ऐसा भी लगता है कि यह इस न्यायपूर्ण world-view के आगे झुकना है कि computer internals के बारे में अपने व्यक्तिगत और बहुत ज़्यादा simplified model से ही दुनिया समझ में आने और reason करने लायक होनी चाहिए। यह approach काफी दूर तक ले जाती है, लेकिन आखिर में dead end है, और अंत में यह मानना पड़ता है कि हम कुछ नहीं जानते, और सही program बनाया है इसका सबसे अच्छा formal argument यही है कि documentation सही होने की शर्त पर वह सही है। यह बड़ा intellectual leap है, और निजी तौर पर, जितना लंबे समय तक मुझे इसे मानने के लिए मजबूर नहीं किया गया, बाद में इसे पार करना उतना कठिन हुआ। फिर भी लगता है कि आजकल beginners में physical electronics projects popular हो रहे हैं, इसलिए उम्मीद है कि “documentation पढ़ो” की जगह “कमबख्त datasheet पढ़ो” नया standard बने
autoconfscript चलाते समय byte में bits की संख्या check करके उसेconfig.hमें save करते देखता हूँ। जैसे कोई सचमुच उस value के आधार पर कुछ करने की योजना बना रहा होcompile process में पूरे पुराने code को check करके यह पता लगाने का तरीका चाहिए कि यह macro पहले से इस्तेमाल हो रहा है या नहीं। ऐसे breaking changes language को split करने का risk भी रखते हैं। यह भी साफ़ नहीं है कि existing codebase
CHAR_BITmacro इस्तेमाल करता है या नहीं, और उसे नए compiler पर update किया जा सकता है या नहीं, यह test करना कितना कठिन होगा। कौन-सी library टूटने वाली मानी जाएगी,CHAR_BITका इस्तेमाल करके compile किए गए दूसरे code के साथ interact करने पर भी problem होगी या नहीं — ऐसे सवाल भी उठते हैं। मैं मानता हूँ कि यह intuition के खिलाफ़ है, लेकिन पहले conversion tool बनाकर यह दिखाना बेहतर होगा कि extreme cases में भी safe है, फिर transition किया जाएयह proposal विवाद-रहित होते हुए भी बेहद तीखा है, इसलिए पसंद आया
int8_t == char == 8 bitsenforce करना पूरी तरह ठीक है, लेकिन byte 8-bit होता है वाली गलतफहमी फैलाने को लेकर भरोसा नहीं है8-bit byte को octet कहते हैं। साथ ही C++17 से
byteपहले से हीcharका “alias” जैसा भी है: https://en.cppreference.com/w/cpp/types/byteउसके बाद 45 साल में “byte” को किसी और अर्थ में इस्तेमाल होते नहीं देखा, इसलिए अगर 8-bit नहीं वाले “byte” की कोई definition है तो source चाहिए
यह descriptive statement नहीं, बल्कि normative statement है
int8 == signed charपसंद नहीं हैstd::cout << (int8_t)32 << std::endl;को स्वाभाविक रूप से 32 print करना चाहिएC++ से सीधे जुड़ा नहीं है, लेकिन 6-bit byte वाले रेट्रो microcomputer का आइडिया मुझे काफी पसंद है। जैसे 24-bit को word माना जाए
Microcomputer आम तौर पर कम संख्या में objects से काम करते हैं और pointers की तुलना में arrays को प्राथमिकता देते हैं, इसलिए memory बचाई जा सकती है। VGA में प्रति color 6 bits थे, 6x4 bit matrix से पढ़ने लायक alphabet बनाया जा सकता है, basic LISP या Forth भाषाओं को भी 6-bit alphabet में फिट किया जा सकता है, और मूल System/360 केवल 24-bit addresses इस्तेमाल करता था। स्वतंत्र रूप से address किए जा सकने वाले 6-bit units की 12MiB memory किसी के लिए भी काफी होनी चाहिए। अगर कम पड़े, तो FAT-12 को स्वाभाविक रूप से FAT-24 तक बढ़ा दें, या 64-bit pointers जितने ही उपयोगी 48-bit pointers इस्तेमाल करें