มาตรฐาน C23 นำเสนอการเปลี่ยนแปลงที่สำคัญในการจัดการประเภทข้อมูล struct, union และ enum ภายในหน่วยการแปลเดียวกัน กฎความเข้ากันได้ของ tag ใหม่นี้พร้อมใช้งานใน GCC 15 และรุ่น Clang ที่กำลังจะมาถึง เปิดประตูสู่รูปแบบการเขียนโปรแกรมที่ยืดหยุ่นมากขึ้นซึ่งเคยเป็นไปไม่ได้มาก่อน
ในอดีต C จะถือว่าการนิยาม struct ที่เหมือนกันภายในหน่วยการแปลเดียวกันเป็นประเภทข้อมูลที่แยกจากกันโดยสิ้นเชิง แม้ว่าจะมีชื่อและฟิลด์เหมือนกันก็ตาม สิ่งนี้สร้างปัญหาความเข้ากันได้และจำกัดความยืดหยุ่นในการเขียนโปรแกรม กฎใหม่เปลี่ยนพฤติกรรมนี้โดยทำให้ struct ที่มี tag และการนิยามฟิลด์ที่ตรงกันสามารถเข้ากันได้ โดยไม่คำนึงถึงว่าจะถูกนิยามไว้ที่ไหนภายในหน่วยการแปลเดียวกัน
การรองรับของคอมไพเลอร์
- GCC 15 : พร้อมใช้งาน (เปิดตัวเมษายน 2024)
- Clang : จะมาในช่วงปลายปี 2024
- ต้องการการปฏิบัติตามมาตรฐาน C23
ประเภทข้อมูลแบบพารามิเตอร์ผ่าน Macros
การประยุกต์ใช้ที่น่าตื่นเต้นที่สุดของการเปลี่ยนแปลงนี้คือความสามารถในการสร้างประเภทข้อมูลแบบพารามิเตอร์คล้าย template โดยใช้ macros นักพัฒนาสามารถนิยามโครงสร้างข้อมูลแบบทั่วไปที่ทำงานกับประเภทข้อมูลต่างๆ ได้โดยไม่ต้องเขียนการนิยามแยกสำหรับแต่ละประเภท สิ่งนี้มีประโยชน์อย่างยิ่งสำหรับการสร้าง dynamic arrays, slices และประเภท container อื่นๆ ที่ต้องทำงานกับประเภทข้อมูลหลากหลาย
เทคนิคนี้เกี่ยวข้องกับการใช้ macros เพื่อสร้างการนิยาม struct ที่มี tag เฉพาะตามประเภทพารามิเตอร์ เมื่อประเภทแบบพารามิเตอร์เดียวกันถูกใช้หลายครั้งในส่วนต่างๆ ของโค้ด คอมไพเลอร์จะรู้จักว่าเป็นประเภทข้อมูลที่เข้ากันได้แทนที่จะเป็นประเภทที่แตกต่างกัน
ข้อเสนอปรับปรุงไวยากรณ์
การอภิปรายในชุมชนเน้นการปรับปรุงเพิ่มเติมที่อาจทำให้เทคนิคนี้ใช้งานได้จริงมากขึ้น ไวยากรณ์ #def #enddef ที่เสนอสำหรับ C2Y จะช่วยขจัดความจำเป็นในการใช้ backslashes ในการนิยาม macro หลายบรรทัด ทำให้การนิยามประเภทแบบพารามิเตอร์อ่านง่ายและดูแลรักษาได้มากขึ้น
ข้อเสนอ #def #enddef ล่าสุดจะช่วยขจัดความจำเป็นในการใช้ backslashes เพื่อนิยาม macros ที่อ่านง่าย ทำให้รูปแบบนี้น่าใช้มากขึ้น
ข้อจำกัดปัจจุบันและวิธีแก้ไข
แม้จะมีศักยภาพ แต่กฎความเข้ากันได้ใหม่ก็มีข้อจำกัดที่น่าสังเกต พารามิเตอร์ macro ต้องเป็น identifier ธรรมดา ซึ่งป้องกันการใช้ประเภทแบบพารามิเตอร์ซ้อนกันเช่น Slice(Slice(float))
นักพัฒนาต้องสร้างการนิยามประเภทข้อมูลระดับกลางเพื่อแก้ไขข้อจำกัดนี้ ซึ่งลดความสะดวกลงบ้าง
นอกจากนี้ แม้ว่าประเภทแบบพารามิเตอร์จะเป็นไปได้แล้ว แต่ฟังก์ชันที่ทำงานกับประเภทเหล่านี้ยังคงต้องการการใช้งานแยกหรือเทคนิคการเขียนโปรแกรมแบบทั่วไป หมายความว่าฟีเจอร์นี้ให้ความยืดหยุ่นของประเภทข้อมูลโดยไม่มีฟังก์ชัน template แบบเต็มรูปแบบ
ข้อจำกัด
- พารามิเตอร์ของ macro ต้องเป็น identifier ที่เรียบง่าย
- ไม่สามารถซ้อน parameterized types โดยตรง (เช่น
Slice(Slice(float))
) - ไม่มีการกำหนดพารามิเตอร์ของ generic function
- ต้องใช้วิธีการแก้ไขชั่วคราวสำหรับการผสมผสานประเภทข้อมูลที่ซับซ้อน
การตอบรับและข้อกังวลของชุมชน
ชุมชนนักเขียนโปรแกรมแสดงปฏิกิริยาที่หลากหลายต่อการเปลี่ยนแปลงนี้ แม้ว่าหลายคนจะชื่นชมความยืดหยุ่นที่เพิ่มขึ้น แต่บางคนก็แสดงความกังวลเกี่ยวกับปัญหาคุณภาพโค้ดที่อาจเกิดขึ้น มีความกังวลว่าความเข้ากันได้ของประเภทข้อมูลที่ผ่อนปรนมากขึ้นอาจทำให้โค้ดที่ไม่ดีสามารถคอมไพล์ได้เมื่อไม่ควรจะเป็นเช่นนั้น แม้ว่าสถานการณ์ที่เป็นปัญหาเฉพาะเจาะจงยังไม่ชัดเจน
การเปลี่ยนแปลงนี้แสดงถึงความสมดุลที่ระมัดระวังระหว่างการรักษาความปลอดภัยของประเภทข้อมูลแบบดั้งเดิมของ C และการให้ความสะดวกในการเขียนโปรแกรมสมัยใหม่ เมื่อนักพัฒนามากขึ้นใช้ C23 และทดลองกับความสามารถใหม่เหล่านี้ ประโยชน์ที่เป็นจริงและข้อผิดพลาดที่อาจเกิดขึ้นจะชัดเจนขึ้น
กฎความเข้ากันได้ของ tag แสดงให้เห็นการพัฒนาต่อเนื่องของ C ในขณะที่รักษาหลักการหลักไว้ แม้ว่าประโยชน์อาจดูเล็กน้อยเมื่อเปรียบเทียบกับระบบ template แบบเต็มรูปแบบในภาษาอื่น แต่ก็ให้เครื่องมือใหม่ที่มีค่าสำหรับนักเขียนโปรแกรม C ที่ทำงานกับโครงสร้างข้อมูลแบบทั่วไปและอินเทอร์เฟซที่ปลอดภัยต่อประเภทข้อมูล
อ้างอิง: Parameterized types in C using the new tag compatibility rule