คุณลักษณะที่น่าสนใจของ C เมื่อเทียบกับภาษาอื่น ๆ คือประเภทข้อมูลจำนวนมากนั้นขึ้นอยู่กับขนาดของคำของสถาปัตยกรรมเป้าหมายแทนที่จะถูกระบุในเงื่อนไขแบบสัมบูรณ์ แม้ว่าสิ่งนี้จะช่วยให้ภาษาสามารถใช้ในการเขียนโค้ดบนเครื่องที่อาจมีปัญหากับบางประเภท แต่ก็เป็นการยากที่จะออกแบบรหัสซึ่งจะทำงานอย่างต่อเนื่องในสถาปัตยกรรมที่แตกต่างกัน พิจารณารหัส:
uint16_t ffff16 = 0xFFFF;
int64_t who_knows = ffff16 * ffff16;
ในสถาปัตยกรรมที่int
มี 16 บิต (ยังคงเป็นจริงของไมโครคอนโทรลเลอร์ขนาดเล็กจำนวนมาก) รหัสนี้จะกำหนดค่า 1 โดยใช้พฤติกรรมที่กำหนดไว้อย่างดี บนเครื่องที่int
มี 64 บิตก็จะกำหนดค่า 4294836225 อีกครั้งโดยใช้พฤติกรรมที่กำหนดไว้อย่างดี บนเครื่องที่int
มี 32 บิตก็น่าจะกำหนดค่า -131071 (ฉันไม่ทราบว่าจะเป็นพฤติกรรมการใช้งานที่กำหนดหรือไม่ได้กำหนด) แม้ว่าโค้ดจะไม่ใช้สิ่งใดนอกจากสิ่งที่ควรจะเป็นในนาม "ประเภทขนาดคงที่" มาตรฐานจะกำหนดให้คอมไพเลอร์สองแบบที่ใช้กันในวันนี้จะให้ผลลัพธ์ที่แตกต่างกันสองแบบและคอมไพเลอร์ยอดนิยมจำนวนมากในปัจจุบัน
ตัวอย่างนี้เป็นการประดิษฐ์ที่ฉันไม่คาดหวังในรหัสโลกแห่งความจริงเพื่อกำหนดผลิตภัณฑ์ของค่า 16 บิตสองค่าโดยตรงกับค่า 64- บิต แต่มันถูกเลือกเป็นตัวอย่างสั้น ๆ เพื่อแสดงจำนวนเต็มสามวิธี การส่งเสริมการขายอาจโต้ตอบกับประเภทที่ไม่ได้ลงชื่อขนาดคงที่ มีสถานการณ์ในโลกจริงบางอย่างที่จำเป็นสำหรับการคำนวณทางคณิตศาสตร์ในประเภทที่ไม่ได้ลงนามตามกฎของเลขคณิตเลขจำนวนเต็มทางคณิตศาสตร์อื่น ๆ ที่จำเป็นที่จะต้องดำเนินการตามกฎของเลขคณิตแบบแยกส่วนและบางอย่างที่มันไม่จริง ' ไม่เป็นไร รหัสโลกแห่งความจริงมากมายสำหรับสิ่งต่าง ๆ เช่นเช็คuint32_t
ซัมขึ้นอยู่กับการห่อเลขคณิต mod 2³²และเมื่อสามารถทำการสุ่มได้uint16_t
เลขคณิตและผลลัพธ์ที่ได้คืออย่างน้อยที่สุดถูกกำหนดว่าเป็น mod ที่ถูกต้อง 65536 (ตรงข้ามกับการเรียกพฤติกรรมที่ไม่ได้กำหนด)
แม้ว่าสถานการณ์นี้จะดูเหมือนไม่เป็นที่ต้องการอย่างชัดเจน (และจะเพิ่มมากขึ้นเมื่อการประมวลผล 64- บิตกลายเป็นบรรทัดฐานสำหรับหลาย ๆ วัตถุประสงค์), คณะกรรมการมาตรฐาน C จากสิ่งที่ฉันสังเกตเห็นชอบที่จะแนะนำคุณสมบัติภาษาที่ใช้ในการผลิตที่โดดเด่นอยู่แล้ว สภาพแวดล้อมมากกว่าการประดิษฐ์พวกเขา "ตั้งแต่เริ่มต้น" มีส่วนขยายที่โดดเด่นของภาษา C ซึ่งอนุญาตให้ใช้รหัสเพื่อระบุไม่ใช่แค่การจัดเก็บประเภท แต่ยังควรปฏิบัติในสถานการณ์ที่เกี่ยวข้องกับการส่งเสริมการขายที่เป็นไปได้หรือไม่ ฉันเห็นอย่างน้อยสามวิธีที่ส่วนขยายคอมไพเลอร์อาจแก้ไขปัญหาดังกล่าว:
โดยการเพิ่มคำสั่งที่จะสั่งให้คอมไพเลอร์บังคับประเภทจำนวนเต็ม "พื้นฐาน" ให้เป็นขนาดที่แน่นอน
โดยการเพิ่มคำสั่งที่จะสั่งให้คอมไพเลอร์ประเมินสถานการณ์การส่งเสริมการขายต่าง ๆ ราวกับว่าประเภทของเครื่องมีขนาดเฉพาะโดยไม่คำนึงถึงขนาดที่แท้จริงของประเภทในสถาปัตยกรรมเป้าหมาย
โดยให้ความหมายของการประกาศประเภทที่มีลักษณะเฉพาะ (เช่นประกาศว่าเป็นชนิดที่ควรประพฤติเป็น mod-65536 ห่อแหวนพีชคณิตโดยไม่คำนึงถึงขนาดคำพื้นฐานและไม่ควรจะเป็นโดยปริยายแปลงสภาพให้แก่ประเภทอื่น ๆ เพิ่ม
wrap32
ไปยังint
ควรให้ผลผลิต ผลของการพิมพ์wrap32
โดยไม่คำนึงว่าint
มีขนาดใหญ่กว่า 16 บิตในขณะที่การเพิ่มwrap32
โดยตรงไปยัง awrap16
ควรผิดกฎหมาย (เนื่องจากไม่สามารถแปลงเป็นอื่นได้)
การตั้งค่าของฉันเองจะเป็นทางเลือกที่สามเนื่องจากมันจะช่วยให้แม้แต่เครื่องที่มีขนาดคำที่ผิดปกติสามารถทำงานกับโค้ดจำนวนมากที่คาดว่าตัวแปรจะ "ห่อ" ตามที่พวกเขาต้องการด้วยขนาดกำลังไฟของสอง; คอมไพเลอร์อาจต้องเพิ่มคำแนะนำการปิดบังบิตเพื่อให้ประเภททำงานได้อย่างเหมาะสม แต่หากรหัสต้องการประเภทที่ห่อ mod 65536 จะดีกว่าที่จะให้คอมไพเลอร์สร้างการปิดบังดังกล่าวบนเครื่องที่ต้องการมันมากกว่าจะยุ่งเหยิงซอร์สโค้ด หรือเพียงแค่มีรหัสดังกล่าวโดยใช้ไม่ได้บนเครื่องที่ต้องการการปิดบังดังกล่าว แม้ว่าฉันจะสงสัยว่ามีส่วนขยายร่วมกันใด ๆ ที่จะบรรลุพฤติกรรมแบบพกพาผ่านวิธีการข้างต้นหรือผ่านวิธีการบางอย่างที่ฉันไม่ได้คิด
เพื่อชี้แจงสิ่งที่ฉันกำลังมองหามีบางสิ่ง; สะดุดตาที่สุด:
ในขณะที่มีหลายวิธีที่จะเขียนรหัสเพื่อให้แน่ใจว่าต้องการความหมาย (e กรัมกำหนดให้ปฏิบัติการทางคณิตศาสตร์ในขนาดเฉพาะ - ตัวถูกดำเนินการลงนามเพื่อให้ได้ผลลัพธ์ที่ชัดเจนหรือไม่ห่อ) หรืออย่างน้อยก็ไม่ต้องการป้องกัน ความหมาย (เช่นเงื่อนไขกำหนดประเภท
wrap32_t
จะเป็นuint32_t
ในคอมไพเลอร์ที่uint32_t
จะไม่ได้รับการส่งเสริมและตัวเลขว่ามันเป็นที่ดีกว่าสำหรับรหัสซึ่งจะต้องมีwrap32_t
การล้มเหลวในการสะสมในเครื่องที่ประเภทที่จะได้รับการส่งเสริมมากกว่าที่จะมีมันทำงานและผลผลิตพฤติกรรมปลอม) หากมีวิธีการเขียนรหัสใดที่จะเล่นได้ดีที่สุดกับส่วนขยายของภาษาในอนาคตการใช้สิ่งนั้นจะดีกว่าการคิดแนวทางของตัวเองฉันมีความคิดที่ชัดเจนเกี่ยวกับวิธีการขยายภาษาเพื่อแก้ไขปัญหาจำนวนเต็มจำนวนมากการอนุญาตให้โค้ดให้ความหมายที่เหมือนกันบนเครื่องที่มีขนาดคำต่างกัน แต่ก่อนที่ฉันจะใช้เวลาสำคัญในการเขียนพวกเขา เพื่อทราบว่าความพยายามในทิศทางนั้นได้ดำเนินไปแล้ว
ฉันไม่ได้ต้องการเห็นว่าเป็นการดูหมิ่นคณะกรรมการมาตรฐาน C หรืองานที่พวกเขาสร้างขึ้น ฉันคาดหวังว่าภายในไม่กี่ปีมันจะมีความจำเป็นในการทำให้โค้ดทำงานอย่างถูกต้องบนเครื่องที่ประเภทการส่งเสริม "ธรรมชาติ" จะมี 32 บิตเช่นเดียวกับที่มันจะเป็น 64 บิต ฉันคิดว่ามีส่วนขยายเล็กน้อยสำหรับภาษา (เล็กน้อยมากกว่าการเปลี่ยนแปลงอื่น ๆ ระหว่าง C99 nnd C14) มันเป็นไปได้ที่จะไม่เพียง แต่มอบวิธีการที่สะอาดอย่างมีประสิทธิภาพโดยใช้สถาปัตยกรรม 64 บิต แต่ในการต่อรองยังอำนวยความสะดวกในการโต้ตอบกับ เครื่องจักรที่ "ผิดปกติ - คำ - ขนาด" ซึ่งเป็นมาตรฐานในอดีตก้มลงไปข้างหลังเพื่อสนับสนุน [e กรัมทำให้เป็นไปได้สำหรับเครื่องที่มีขนาด 12 บิตchar
เพื่อเรียกใช้โค้ดที่คาดว่าuint32_t
เพื่อห่อ mod 2³²] ขึ้นอยู่กับทิศทางการขยายในอนาคตฉันก็คาดหวังว่ามันจะเป็นไปได้ที่จะกำหนดมาโครซึ่งจะอนุญาตให้โค้ดที่เขียนในวันนี้สามารถใช้งานได้ในคอมไพเลอร์ในวันนี้ซึ่งประเภทจำนวนเต็มเริ่มต้นจะทำหน้าที่เป็น "คาดหวัง" ประเภทจะเป็นค่าเริ่มต้นพฤติกรรมที่แตกต่างกัน แต่สามารถให้พฤติกรรมที่จำเป็น
int
แต่ก็ยังย่องเข้ามา (สมมติว่าฉันเข้าใจมาตรฐาน C ถูกต้องอีกครั้ง)
int
มีขนาดใหญ่กว่าuint16_t
, ตัวถูกดำเนินการของคูณจะได้รับการเลื่อนตำแหน่งให้เป็นint
และการคูณจะได้รับการดำเนินการเป็นint
คูณและเกิดint
ความคุ้มค่าจะถูกแปลงสำหรับการเริ่มต้นของint64_t
who_knows