#import "../PageTemplate.typ": * #import "@preview/i-figured:0.2.4" = ภาษาซี (C Programming Language) #h(2.25em) ภาษาซีเป็นภาษาโปรแกรมสำหรับวัตถุประสงค์ทั่วไปสร้างขึ้นในช่วงทศวรรษ 1970 โดยเดนนิสริตชีและยังคงได้รับความนิยมและใช้งานอย่างกว้างขวางด้วยการออกแบบภาษาซีทำให้โปรแกรมเมอร์สามารถเข้าถึงคุณลักษณะต่างๆของสถาปัตยกรรมซีพียูทั่วไปได้โดยตรง ซึ่งปรับแต่งให้เหมาะกับชุดคำสั่ง เป้าหมาย ภาษาซี ถูกนำมาใช้และยังคงนำมาใช้ในการพัฒนาระบบปฏิบัติการไดรเวอร์อุปกรณ์และสแต็กโปรโตคอลแต่การใช้งานในซอฟต์แวร์แอปพลิเคชั่นกำลังลดลงภาษาซีถูกนำมาใช้ในคอมพิวเตอร์ตั้งแต่ซูเปอร์คอมพิวเตอร์ขนาดใหญ่ที่สุดไปจนถึงไมโครคอนโทรลเลอร์ขนาดเล็กที่สุดและระบบฝังตัว #h(2.25em) ภาษาซีเป็นภาษาเชิงกระบวนการที่จำเป็นรองรับการเขียนโปรแกรมแบบมีโครงสร้างขอบเขตตัวแปรเชิงศัพท์และการเรียกซ้ำด้วยระบบชนิดข้อมูลแบบคงที่ภาษาซีถูกออกแบบมาเพื่อการคอมไพล์เพื่อให้สามารถเข้าถึงหน่วยความจำ และโครงสร้างภาษา ในระดับต่ำซึ่งแมปกับคำสั่งเครื่องได้อย่างมีประสิทธิภาพ โดยทั้งหมดนี้รองรับรันไทม์ขั้นต่ำ แม้จะมีความสามารถในระดับต่ำ แต่ภาษาซีก็ถูกออกแบบมาเพื่อสนับสนุนการเขียนโปรแกรมข้ามแพลตฟอร์ม โปรแกรมซี ที่สอดคล้องกับมาตรฐานที่เขียนขึ้นโดยคำนึงถึงความสามารถในการพกพาสามารถคอมไพล์สำหรับแพลตฟอร์มคอมพิวเตอร์และระบบปฏิบัติการที่หลากหลาย โดยมีการเปลี่ยนแปลงซอร์สโคดเพียงเล็กน้อย #h(2.25em) แม้ว่าทั้งภาษาซีและไลบรารีมาตรฐานของภาษา ซีจะไม่ได้มีคุณสมบัติยอดนิยมบางอย่างที่พบในภาษาอื่น แต่ก็มีความยืดหยุ่นเพียงพอที่จะรองรับคุณสมบัติเหล่านั้นได้ ตัวอย่างเช่นการวางแนววัตถุและการเก็บขยะนั้นจัดทำโดยไลบรารีภายนอก GLib Object System และ Boehm garbage collector ตามลำดับ #h(2.25em) ตั้งแต่ปี 2000 เป็นต้นมาภาษาซี ได้รับการจัดอันดับอย่างต่อเนื่องให้อยู่ในอันดับสี่ภาษาสูงสุดในดัชนี TIOBE ซึ่งเป็นการวัดความนิยมของภาษาการเขียนโปรแกรม == ประวัติ === การพัฒนาช่วงแรก #h(8.85em) ที่มาของภาษา C มีความเชื่อมโยงอย่างใกล้ชิดกับการพัฒนาระบบปฏิบัติการ#jb Unix ซึ่งเดิมทีเขียนด้วยภาษาแอสเซมบลีบน PDP-7 โดย Dennis Ritchie และ Ken Thompson โดยนำแนวคิดหลายอย่างจากเพื่อนร่วมงานมาใช้ ในที่สุดพวกเขาก็ตัดสินใจย้ายระบบปฏิบัติการไปยัง PDP-11 เวอร์ชัน Unix ดั้งเดิมบน PDP-11 ก็ได้รับการพัฒนาด้วยภาษาแอสเซมบลีเช่นกัน === ภาษา B #h(8.85em) ทอมป์สันต้องการภาษาโปรแกรมสำหรับการพัฒนายูทิลิตี้สำหรับแพลตฟอร์มใหม่ เขาพยายามเขียนคอมไพเลอร์ Fortran ก่อน แต่ในไม่ช้าเขาก็ล้มเลิกความคิดนั้นและสร้างเวอร์ชันย่อของภาษาโปรแกรมระบบ ที่พัฒนาขึ้นใหม่ชื่อ BCPL แทน คำอธิบายอย่างเป็นทางการของ BCPL ยังไม่พร้อมใช้งานในขณะนั้นและทอมป์สันได้แก้ไขไวยากรณ์ให้ "กระชับ" น้อยลงและคล้ายกับ ALGOL ที่เรียบง่ายกว่า ที่เรียกว่า SMALGOL เขาเรียกผลลัพธ์ นี้ว่า B โดยอธิบายว่าเป็น#jb "ความหมายของ BCPL ที่มีไวยากรณ์ SMALGOL จำนวนมาก" เช่นเดียวกับ BCPL, B มีคอมไพเลอร์ บูตสแตรปเพื่ออำนวยความสะดวกในการพอร์ตไปยังเครื่องใหม่ในที่สุด มีการเขียนยูทิลิตี้เพียงไม่กี่ตัวใน B เพราะมันช้าเกินไปและไม่สามารถใช้ประโยชน์จากคุณสมบัติของ PDP-11 เช่นการเข้าถึงที่อยู่ไบต์ได้ === ภาษา B ใหม่และ C รุ่นแรก #h(8.85em) ในปี พ.ศ. 2514 ริชชีเริ่มปรับปรุง B เพื่อใช้คุณสมบัติของ PDP-11 ที่ทรงพลังยิ่งขึ้น การเพิ่มเติมที่สำคัญคือประเภทข้อมูลอักขระ เขาเรียกสิ่งนี้ว่า New B (NB) ทอมป์สันเริ่มใช้ NB เพื่อเขียน เคอร์เนล Unix และข้อกำหนดของเขากำหนดทิศทางการพัฒนาภาษา จนถึงปี 1972 มีการเพิ่มประเภทข้อมูลที่หลากหลายมากขึ้นให้กับภาษา NB ภาษา NB มีอาร์เรย์ของ int และ char และได้มีการเพิ่มพอยเตอร์ ความสามารถในการสร้างพอยเตอร์ไปยังประเภทอื่นๆ อาร์เรย์ของทุกประเภท และประเภทที่จะส่งคืนจากฟังก์ชัน อาร์เรย์ภายในนิพจน์ได้รับการปฏิบัติเสมือนเป็นพอยเตอร์ มีการเขียนคอมไพเลอร์ใหม่ และเปลี่ยนชื่อภาษาเป็น C #h(8.85em) คอมไพเลอร์ C และยูทิลิตี้บางส่วนที่สร้างขึ้นด้วยคอมไพเลอร์นี้ถูกรวมอยู่ใน Unix เวอร์ชัน 2 ซึ่งเรียกอีกอย่างว่า Research Unix === โครงสร้างและการเขียน Unix kernel ใหม่ #h(8.85em) ใน Unix เวอร์ชัน 4 ซึ่งวางจำหน่ายในเดือนพฤศจิกายน พ.ศ. 2516 เคอร์เนลของ Unix ได้รับการเขียนใหม่อย่างกว้างขวางด้วยภาษา C ในเวลานั้น ภาษา C ได้รับคุณสมบัติที่ทรงพลังบางอย่างเช่นประเภท struct #h(8.85em) ตัวประมวลผลล่วงหน้าได้รับการแนะนำประมาณปี 1973 ตามคำแนะนำของ Alan Snyder และยังเป็นการยอมรับถึงประโยชน์ของกลไกการรวมไฟล์ที่มีอยู่ใน BCPL และPL/I เวอร์ชันดั้งเดิมให้เฉพาะไฟล์ที่รวมไว้และการแทนที่สตริงแบบง่ายเท่านั้น `#include` รวม `#define` ถึงมาโครที่ไม่มีพารามิเตอร์ หลังจากนั้นไม่นาน ก็มีการขยายเพิ่มเติม โดยส่วนใหญ่โดย Mike Lesk และต่อมาโดย John Reiser เพื่อรวมมาโครที่มีอาร์กิวเมนต์และการคอมไพล์แบบมีเงื่อนไข #h(8.85em) Unix เป็นหนึ่งในเคอร์เนลระบบปฏิบัติการแรกๆ ที่เขียนด้วยภาษาอื่นที่ไม่ใช่ภาษาแอสเซมบลีตัวอย่างก่อนหน้านี้ได้แก่ ระบบ Multics (ซึ่งเขียนด้วยภาษา PL/I) และ Master Control Program (MCP) สำหรับ Burroughs B5000 (ซึ่งเขียนด้วยภาษา ALGOL) ในปี 1961 ในช่วงปี 1977 Ritchie และ Stephen C. Johnson ได้ทำการเปลี่ยนแปลงเพิ่มเติมให้กับภาษาเพื่ออำนวยความสะดวกในการพกพาระบบปฏิบัติการUnix คอมไพเลอร์ Portable C ของ Johnson เป็นพื้นฐานสำหรับการใช้งาน C บนแพลตฟอร์มใหม่ๆ หลายแพลตฟอร์ม === K&R C #h(8.85em) ในปี พ.ศ. 2521 Brian KernighanและDennis Ritchie ได้ตีพิมพ์หนังสือ The C Programming Language ฉบับพิมพ์ครั้งแรกหนังสือเล่มนี้รู้จักกันในชื่อย่อ K&R ตามชื่อย่อของผู้เขียนและทำหน้าที่เป็นข้อกำหนดที่ไม่เป็นทางการ ของภาษาเป็นเวลาหลายปีเวอร์ชันของภาษา C ที่อธิบายไว้ในหนังสือเล่มนี้มักเรียกกันว่า "K&R C" เนื่องจาก หนังสือเล่มนี้ได้รับการเผยแพร่ในปี พ.ศ. 2521 จึงเรียกอีกอย่างว่า C78 หนังสือฉบับพิมพ์ครั้งที่สองครอบคลุมมาตรฐาน ANSI C ในภายหลัง ซึ่งจะกล่าวถึงต่อไป #h(8.85em) K&R ได้เพิ่มฟีเจอร์ด้านภาษาหลายอย่าง #[ #set enum(indent: 8.85em) 1. ไลบรารีอินพุต/เอาต์พุตมาตรฐาน 2. long int ประเภทข้อมูล 3. unsigned int ประเภทข้อมูล 4. ตัวดำเนินการกำหนดค่าแบบผสมในรูปแบบ =_op_ (เช่น `=-`) ถูกเปลี่ยนเป็นรูปแบบ _op_= (นั่นคือ `-=`) เพื่อขจัดความกำกวมทางความหมายที่เกิดจากโครงสร้างเช่น `i=-10` ซึ่งถูกตีความว่า `i =- 10` (ลด `i` ลง 10) แทนที่จะเป็นความหมายที่ตั้งใจไว้ (ให้ `i` เป็น -10) ] #h(8.85em) แม้หลังจากมีการเผยแพร่มาตรฐาน ANSI ปี 1989 แล้วก็ตาม เป็นเวลาหลายปีที่ K&R C ยังคงถูกพิจารณาว่าเป็น "ตัวหารร่วมที่ต่ำที่สุด" ที่โปรแกรมเมอร์ภาษา C ยึดถือเมื่อต้องการความสามารถในการพกพาได้สูงสุด เนื่องจากคอมไพเลอร์รุ่นเก่าจำนวนมากยังคงถูกใช้งานอยู่และเนื่องจากโค้ด K&R C ที่เขียนอย่างระมัดระวังก็สามารถเป็นไปตามมาตรฐาน C ได้เช่นกัน #h(8.85em) แม้ว่า C เวอร์ชันต่อมาจะกำหนดให้ฟังก์ชันต้องมีการประกาศประเภทอย่างชัดเจนแต่ C เวอร์ชัน K&R กำหนดให้ฟังก์ชันที่ส่งคืนค่าประเภทอื่นที่ไม่ใช่ประเภท ที่กำหนดไว้เท่านั้น int ที่จะต้องประกาศก่อนใช้งาน ฟังก์ชันที่ใช้โดยไม่มีการประกาศล่วงหน้าจะถือว่าส่งคืนค่าประเภทที่กำหนด int ไว้ === ANSI C และ ISO C #h(8.85em) ในช่วงปลายทศวรรษ 1970 และ 1980 ภาษา C เวอร์ชันต่างๆ ถูกนำไปใช้งานใน คอมพิวเตอร์เมนเฟรมมินิคอมพิวเตอร์และไมโครคอมพิวเตอร์หลากหลายรุ่นรวมถึง IBM PC ด้วย เนื่องจากความนิยมของคอมพิวเตอร์ประเภทนี้เพิ่มขึ้นอย่างมาก #h(8.85em) ในปี 1983 สถาบันมาตรฐานแห่งชาติอเมริกัน (ANSI) ได้จัดตั้งคณะกรรมการ#jb X3J11 เพื่อกำหนดมาตรฐานของภาษา C X3J11 ใช้มาตรฐาน C ที่อิงตามการใช้งานบนระบบ Unix เป็นพื้นฐาน อย่างไรก็ตามส่วนที่ไม่สามารถพกพาได้ของไลบรารี C บน Unix ได้ถูกส่งต่อไปยังกลุ่มทำงาน IEEE 1003 เพื่อใช้เป็นพื้นฐานสำหรับ มาตรฐาน POSIX ในปี 1988 ในปี 1989 มาตรฐาน C ได้รับการรับรองเป็น ANSI X3.159-1989 "ภาษาโปรแกรม C" เวอร์ชันนี้ของภาษามักถูกเรียกว่า ANSI C, Standard C หรือบางครั้งเรียกว่า C89 #h(8.85em) ในปี 1990 มาตรฐาน ANSI C (พร้อมการเปลี่ยนแปลงรูปแบบ) ได้รับการรับรองโดยองค์การมาตรฐานสากล (ISO) ในชื่อ ISO/IEC 9899:1990 ซึ่งบางครั้งเรียกว่า C90 ดังนั้น คำว่า "C89" และ "C90" จึงหมายถึงภาษาโปรแกรมเดียวกัน #h(8.85em) เช่นเดียวกับองค์กรมาตรฐานแห่งชาติอื่นๆ ANSI ไม่ได้พัฒนามาตรฐาน C ด้วยตนเองอีกต่อไป แต่จะอ้างอิงถึงมาตรฐาน C สากล ซึ่งดูแลโดยคณะทำงาน ISO/IEC JTC1/SC22 /WG14 การนำมาตรฐานสากลฉบับปรับปรุงมาใช้ในระดับประเทศมักเกิดขึ้นภายในหนึ่งปีหลังจากที่ ISO เผยแพร่มาตรฐานดังกล่าว #h(8.85em) หนึ่งในเป้าหมายของกระบวนการกำหนดมาตรฐานภาษา C คือการสร้างซูเปอร์เซ็ตของ K&R C โดยรวมเอาคุณสมบัติที่ไม่เป็นทางการหลายอย่างที่ถูกนำมาใช้ในภายหลัง คณะกรรมการมาตรฐานยังได้เพิ่มคุณสมบัติเพิ่มเติมอีกหลายอย่างเช่นต้นแบบฟังก์ชัน (ยืมมาจาก C++), voidพอยเตอร์, การรองรับชุดอักขระและภาษาท้องถิ่นระหว่างประเทศ และการปรับปรุงพรีโปรเซสเซอร์ แม้ว่าไวยากรณ์สำหรับการประกาศพารามิเตอร์จะได้รับการปรับปรุงให้รวมรูปแบบที่ใช้ใน C++ แต่ก็ยังคงอนุญาตให้ใช้อินเทอร์เฟซ K&R เพื่อความเข้ากันได้กับซอร์สโค้ดที่มีอยู่ #h(8.85em) C89 ได้รับการสนับสนุนจากคอมไพเลอร์ C ในปัจจุบัน และโค้ด C สมัยใหม่ส่วนใหญ่ก็ใช้ C89 เป็นพื้นฐานโปรแกรมใดๆ ที่เขียนด้วยภาษา C มาตรฐานเท่านั้น และไม่มีข้อสมมติฐานใดๆ ที่ขึ้นอยู่กับฮาร์ดแวร์ จะทำงานได้อย่างถูกต้องบนแพลตฟอร์มใดๆ ที่มีการใช้งาน C ที่สอดคล้องกับมาตรฐาน ภายในขีดจำกัดของทรัพยากร หากไม่ระมัดระวัง โปรแกรมอาจคอมไพล์ได้เฉพาะบนแพลตฟอร์มใดแพลตฟอร์มหนึ่ง หรือด้วยคอมไพเลอร์เฉพาะเท่านั้น ตัวอย่างเช่น เนื่องจากการใช้ไลบรารีที่ไม่เป็นมาตรฐาน เช่น ไลบรารี GUI หรือการพึ่งพาคุณลักษณะเฉพาะของคอมไพเลอร์หรือแพลตฟอร์ม เช่น ขนาดที่แน่นอนของชนิดข้อมูลและลำดับไบต์ #h(8.85em) ในกรณีที่โค้ดต้องสามารถคอมไพล์ได้ทั้งโดยคอมไพเลอร์ที่สอดคล้องกับมาตรฐานหรือคอมไพเลอร์ที่ใช้ C แบบ K&R นั้น `__STDC__` สามารถใช้มาโครเพื่อแบ่งโค้ดออกเป็นส่วนมาตรฐานและส่วน K&R เพื่อป้องกันการใช้คุณสมบัติที่มีเฉพาะใน C มาตรฐานบนคอมไพเลอร์ที่ใช้ C แบบ K&R #h(8.85em) หลังจากกระบวนการกำหนดมาตรฐาน ANSI/ISO ข้อกำหนดภาษา C ยังคงค่อนข้างคงที่เป็นเวลาหลายปี ในปี 1995 มีการเผยแพร่การแก้ไขมาตรฐานฉบับที่ 1 ของมาตรฐาน C ปี 1990 (ISO/IEC 9899/AMD1:1995 ซึ่งเรียกกันอย่างไม่เป็นทางการว่า C95) เพื่อแก้ไขรายละเอียดบางประการและเพิ่มการสนับสนุนชุดอักขระสากลที่ครอบคลุมมากขึ้น === C99 #h(8.85em) มาตรฐาน C ได้รับการแก้ไขเพิ่มเติมในช่วงปลายทศวรรษ 1990 ส่งผลให้มีการตีพิมพ์ ISO/IEC 9899:1999 ในปี 1999 ซึ่งโดยทั่วไปเรียกว่า "C99" ต่อมาได้มีการแก้ไขเพิ่มเติมอีกสามครั้งโดย Technical Corrigenda #h(8.85em) C99 ได้นำเสนอคุณสมบัติใหม่หลายประการรวมถึงฟังก์ชันอินไลน์ชนิดข้อมูลใหม่หลายชนิด(รวมถึง long long intชนิด ข้อมูล complex ที่ใช้แทนจำนวนเชิงซ้อน) อาร์เรย์ที่มีความยาวแปรผันได้และสมาชิกอาร์เรย์ที่ยืดหยุ่นการสนับสนุนที่ดีขึ้นสำหรับเลขทศลอย IEEE 754 การสนับสนุนมาโครแบบแปรผัน (มาโครที่มีจำนวนอาร์กิวเมนต์ แปรผันได้) และการสนับสนุนความคิดเห็นแบบบรรทัดเดียวที่ขึ้นต้นด้วย `@` `//` เช่นเดียวกับใน BCPL หรือ C++ คุณสมบัติเหล่านี้หลายอย่างได้ถูกนำไปใช้เป็นส่วนขยายในคอมไพเลอร์ C หลายตัวแล้ว #h(8.85em) โดยส่วนใหญ่แล้ว C99 สามารถใช้งานร่วมกับ C90 ได้ แต่มีความเข้มงวดมากกว่าในบางด้าน โดยเฉพาะอย่างยิ่ง การประกาศที่ไม่มีตัวระบุประเภทจะไม่ถือว่ามีintการกำหนดโดยปริยายอีกต่อไป มีการกำหนดมาโครมาตรฐาน `__STDC_VERSION__` พร้อมค่า `199901L` เพื่อระบุว่ามีการสนับสนุน C99 คอม ไพเลอร์ C อื่นๆ เช่น GCC, Solaris Studio และคอมไพเลอร์ C อื่นๆ ในปัจจุบันรองรับคุณสมบัติใหม่หลายอย่างหรือทั้งหมดของ C99 อย่างไรก็ตาม คอมไพเลอร์ C ใน Microsoft Visual C++ ใช้มาตรฐาน C89 และส่วนต่างๆ ของ C99 ที่จำเป็นสำหรับการใช้งานร่วมกับ C++11 #h(8.85em) นอกจากนี้ มาตรฐาน C99 ยังกำหนดให้รองรับตัวระบุที่ใช้ Unicode ในรูปแบบของอักขระพิเศษ (เช่น `\u0040` หรือ `\U0001f431`) และแนะนำให้รองรับชื่อ Unicode ดิบด้วย === C11 #h(8.85em) งานปรับปรุงมาตรฐาน C ฉบับใหม่เริ่มขึ้นในปี 2550 โดยเรียกกันอย่างไม่เป็นทางการว่า "C1X" จนกระทั่งมีการประกาศใช้มาตรฐาน ISO/IEC 9899:2011 อย่างเป็นทางการในวันที่ 8 ธันวาคม 2554 คณะกรรมการมาตรฐาน C ได้กำหนดแนวทางเพื่อจำกัดการนำคุณสมบัติใหม่ๆ ที่ยังไม่ได้รับการทดสอบโดยระบบที่มีอยู่มาใช้ #h(8.85em) มาตรฐาน C11 เพิ่มคุณสมบัติใหม่มากมายให้กับภาษา C และไลบรารี รวมถึงมาโครแบบเจเนริกชนิดโครงสร้างนิรนามการสนับสนุน Unicode ที่ดีขึ้น การดำเนินการอะตอมิกการทำงานแบบมัลติเธรดและฟังก์ชันตรวจสอบขอบเขต นอกจากนี้ยังทำให้บางส่วนของไลบรารี C99 ที่มีอยู่เป็นตัวเลือก และปรับปรุงความเข้ากันได้กับ C++ มาโครมาตรฐาน `__STDC_VERSION__` ถูกกำหนดไว้เพื่อ `201112L` ระบุว่ามีการสนับสนุน C11 แล้ว === C17 #h(8.85em) C17 เป็นชื่อเรียกอย่างไม่เป็นทางการของ ISO/IEC 9899:2018 ซึ่งเป็นมาตรฐานสำหรับภาษาโปรแกรม C ที่เผยแพร่ในเดือนมิถุนายน 2018 มาตรฐานนี้ไม่ได้เพิ่มคุณสมบัติใหม่ใดๆ ให้กับภาษา แต่เป็นการแก้ไขทางเทคนิคและการชี้แจงข้อบกพร่องใน C11 เท่านั้น มาโครมาตรฐาน `__STDC_VERSION__` ถูกกำหนดขึ้นเพื่อ `201710L` ระบุว่ามีการรองรับ C17 แล้ว === C23 #h(9.4em) C23 เป็นชื่อเรียกอย่างไม่เป็นทางการของการแก้ไขมาตรฐานภาษา C หลักในปัจจุบัน ซึ่งในระหว่างการพัฒนาส่วนใหญ่เรียกว่า "C2X" โดยสร้างขึ้นจากเวอร์ชันก่อนหน้า และแนะนำคุณสมบัติใหม่ เช่น คำหลักใหม่ ความหมายเพิ่มเติมสำหรับเพื่อ `auto` ให้มีการอนุมานประเภทเมื่อประกาศตัวแปรประเภทใหม่รวมถึง `nullptr_t` และ `_BitInt` (N) และการขยายไลบรารีมาตรฐาน C23 ได้รับการเผยแพร่ในเดือนตุลาคม 2024 ในชื่อ ISO/IEC 9899:2024 มาโครมาตรฐาน `__STDC_VERSION__` ถูกกำหนดไว้ `202311L` เพื่อระบุว่ามีการสนับสนุน C23 === C2Y #h(9.4em) C2Y เป็นชื่อเรียกอย่างไม่เป็นทางการของการแก้ไขมาตรฐานภาษา C ครั้งใหญ่ถัดไป หลังจาก C23 (C2X) ซึ่งคาดว่าจะออกในช่วงปลายทศวรรษ 2020 ดังนั้นจึงมีเลข '2' ใน "C2Y" ร่างฉบับแรกของ C2Y ได้รับการเผยแพร่ในเดือนกุมภาพันธ์ 2024 ในชื่อ N3220 โดยกลุ่มทำงาน ISO/IEC JTC1/SC22 /WG14 === Embedded C #h(9.4em) ในอดีตการเขียนโปรแกรม C สำหรับระบบฝังตัวจำเป็นต้องใช้ส่วนขยายที่ไม่เป็นมาตรฐานของภาษา C เพื่อรองรับคุณสมบัติพิเศษ เช่นการคำนวณเลขทศนิยมคงที่ ธนาคารหน่วยความจำหลายชุดที่แตกต่างกันและการดำเนินการอินพุต/เอาต์พุตพื้นฐาน #h(9.4em) ในปี 2551 คณะกรรมการมาตรฐาน C ได้เผยแพร่รายงานทางเทคนิคที่ขยายภาษา C เพื่อแก้ไขปัญหาเหล่านี้โดยการจัดหามาตรฐานทั่วไปสำหรับการใช้งานทั้งหมดให้ปฏิบัติตาม ซึ่งรวมถึงคุณสมบัติหลายอย่างที่ไม่มีในภาษา C ปกติ เช่น การคำนวณเลขทศนิยมคงที่ พื้นที่แอดเดรสแบบมีชื่อและการกำหนดแอดเดรสฮาร์ดแวร์ I/O พื้นฐาน == ตัวแปร (Variables) #h(5.05em) ตัวแปรในภาษา C เบื้องต้นแล้วประกอบไปด้วยประเภทของข้อมูลและชื่อตัวแปร โดยที่ชื่อตัวแปรนั้นสามารถเป็นรายการที่ถูกแบ่งด้วยเครื่องหมายจุลภาคได้ด้วยเช่นกัน ตัวอย่างคือ #afigure( ```c int data; float a, b, c; ```, kind: image, caption: [ตัวอย่างการประกาศตัวแปรในภาษา C], ) == ประเภทข้อมูล (Data Types) #h(5.05em) ข้อมูลที่เกี่ยวข้องกับตัวเลขมักมีประเภท unsigned และ signed โดยความแตกต่างหากอธิบายสั้น ๆ คือ #[ #set enum(indent: 5.05em) 1. Signed (มีเครื่องหมาย): ตัวเลขที่สามารถติดลบได้ ระยะข้อมูลตัวอย่างคือ -128 ถึง#jb 127 2. Unsigned (ไม่มีเครื่องหมาย): ตัวเลขที่ไม่สามารถติดลบได้ ระยะข้อมูลตัวอย่างคือ 0 ถึง 255 ] #h(5.05em) จะสังเกตได้ว่า ข้อมูลประเภท unsigned นั้นสามารถเก็บตัวเลขบวกได้จำนวนมากกว่า คือสูงสุดที่ 255 แต่หากนำค่าสัมบูรณ์ (absolute value) ของระยะข้อมูลแบบ signed มาบวกกัน เช่น\ #math.equation($|-128| + |127|$, alt: "ค่าสัมบูรณ์ของ -128 บวกค่าสัมบูรณ์ของ 127") จะพบว่าได้ค่า 255 หมายความว่า จริง ๆ แล้วข้อมูลประเภท signed สามารถเก็บข้อมูลได้ 255 ตัวเลขเช่นกัน เพียงแต่ว่าครึ่งหนึ่งของตัวเลขที่สามารถเก็บได้เป็นตัวเลขติดลบ #h(5.05em) ดังนั้นโปรดจำไว้ว่า เลขคณิตจำนวนเต็มมีนิยามแตกต่างกันสำหรับชนิดจำนวนเต็มแบบ signed และ unsigned โปรดดูตัวดำเนินการเลขคณิต โดยเฉพาะอย่างยิ่งการโอเวอร์โฟลว์จำนวนเต็ม === ประเภทบูลีน (Boolean) #h(8.85em) ประเภทบูลีนนั้นถูกนำเสนอครั้งแรกในมาตรฐาน C99 โดยการกล่าวถึงประเภทข้อมูลบูลีนนั้น ในประวัติของภาษา C แล้วมีสองแบบ #set enum(indent: 8.85em) + `_Bool` (และมีมาโคร `bool`): จนถึงมาตรฐาน C23 + `bool` (ที่ไม่ใช่แค่มาโคร): มีตั้งแต่มาตรฐาน C23 === ประเภทจำนวนเต็ม (Integer) 1. `short int` (หรืออีกชื่อหนึ่งคือ `short` และสามารถใช้คีย์เวิร์ด `signed` ได้) 2. `unsigned short int` (หรือ `unsigned short`) 3. `int` (หรือ `signed int`) \ คือประเภทข้อมูลตัวเลขที่ปกติที่สุด และจะถูกการันตีว่าจะมีขนาดขั้นต่ำ 16 บิตเสมอ โดยระบบทั่วไปส่วนใหญ่ในปัจจุบันจะเป็น 32 บิต 4. `unsigned int` (หรือเพียงแค่ `unsigned`) คือประเภท `int` ในแบบ `unsigned`, มี modulo arithmetic, และเหมาะสมสำหรับการเปลี่ยนแปลงบิต 5. `long int` (หรือ `long`) 6. `unsigned long int` (หรือ `unsigned long`) 7. มีเพิ่มตั้งแต่ C99 #listy( indent: 10.20em, numbering: thai-numbering, [`long long int` (หรือ `long long`)], [`unsigned long long int` (หรือ `unsigned long long`)], ) #v(0.4em) 8. มีเพิ่มตั้งแต่ C23 #listy( indent: 10.20em, numbering: thai-numbering, [`_BitInt(n)` (หรือ `signed _BitInt(n)`): ประเภทข้อมูล signed แบบมีขนาดชัดเจน โดย n แทนด้วยจำนวนบิต (รวมถึงบิตเครื่องหมาย และ n จะต้องไม่มากกว่า `BITINT_MAXWIDTH` จากไฟล์ ``)], [`unsigned _BitInt(n)`: เหมือนข้างต้น เพียงแค่เป็นประเภท unsigned (และไม่มีบิตเครื่องหมาย)], ) และเหมือนประเภทข้อมูลอื่น ๆ คุณสามารถเรียงคีย์เวิร์ดแบบใดก็ได้ เช่น `unsigned long long int` และ `long int unsigned long` นั้นเหมือนกัน ตารางต่อไปนี้สรุปประเภทตัวเลขทั้งหมดและคุณสมบัติของมัน #show table.cell.where(y: 1): strong #show table.cell: set par(justify: false, leading: 0.5em) #figure( table( columns: 7, align: horizon + center, table.header( table.cell([ชื่อประเภท], rowspan: 2), table.cell([ประเภทเทียบเท่า], rowspan: 2), table.cell([จำนวนบิตตามรูปแบบข้อมูล], colspan: 5), [มาตรฐาน C], [LP32], [ILP32], [LLP64], [LP64], ), table.cell(`char`, align: left), `char`, table.cell([อย่างน้อย\ 8], rowspan: 3), table.cell([8], rowspan: 3), table.cell([8], rowspan: 3), table.cell([8], rowspan: 3), table.cell([8], rowspan: 3), table.cell(`signed char`, align: left), `signed char`, table.cell(`unsigned char`, align: left), `unsigned char`, table.cell(`short`, align: left), table.cell(`short int`, rowspan: 4), table.cell([อย่างน้อย\ 16], rowspan: 6), table.cell([16], rowspan: 6), table.cell([16], rowspan: 6), table.cell([16], rowspan: 6), table.cell([16], rowspan: 6), table.cell(`short int`, align: left), table.cell(`signed short`, align: left), table.cell(`signed short int`, align: left), table.cell(`unsigned short`, align: left), table.cell([`unsigned`\ `short int`], rowspan: 2), table.cell(`unsigned short int`, align: left), ), caption: [ขนาดของข้อมูลเป็นบิต], ) #pagebreak() #figure( table( columns: 7, align: horizon + center, table.header( table.cell([ชื่อประเภท], rowspan: 2), table.cell([ประเภทเทียบเท่า], rowspan: 2), table.cell([จำนวนบิตตามรูปแบบข้อมูล], colspan: 5), [มาตรฐาน C], [LP32], [ILP32], [LLP64], [LP64], ), table.cell(`int`, align: left), table.cell(`int`, rowspan: 3), table.cell([อย่างน้อย\ 16], rowspan: 5), table.cell([16], rowspan: 5), table.cell([32], rowspan: 5), table.cell([32], rowspan: 5), table.cell([32], rowspan: 5), table.cell(`signed`, align: left), table.cell(`signed int`, align: left), table.cell(`unsigned`, align: left), table.cell([`unsigned int`], rowspan: 2), table.cell(`unsigned int`, align: left), table.cell(`long`, align: left), table.cell(`long int`, rowspan: 4), table.cell([อย่างน้อย\ 32], rowspan: 6), table.cell([32], rowspan: 6), table.cell([32], rowspan: 6), table.cell([32], rowspan: 6), table.cell([64], rowspan: 6), table.cell(`long int`, align: left), table.cell(`signed long`, align: left), table.cell(`signed long int`, align: left), table.cell(`unsigned long`, align: left), table.cell([`unsigned`\ `long int`], rowspan: 2), table.cell(`unsigned long int`, align: left), table.cell(`long long`, align: left), table.cell([`long long int` (C99)], rowspan: 4), table.cell([อย่างน้อย\ 64], rowspan: 6), table.cell([64], rowspan: 6), table.cell([64], rowspan: 6), table.cell([64], rowspan: 6), table.cell([64], rowspan: 6), table.cell(`long long int`, align: left), table.cell(`signed long long`, align: left), table.cell(`signed long long int`, align: left), table.cell(`unsigned long long`, align: left), table.cell([`unsigned long`\ `long int` (C99)], rowspan: 2), table.cell(`unsigned long long int`, align: left), ), caption: [ขนาดของข้อมูลเป็นบิต (ต่อ)], ) #h(12em) 1) รูปแบบข้อมูล (data model) #h(13.15em) รูปแบบข้อมูล หรือ data model คือรูปแบบการเก็บข้อมูลของโปรแกรมซึ่งเป็นสิ่งที่กำหนดขนาดของตัวแปร โดยรูปแบบข้อมูลนั้นจะถูกกำหนดโดยแพลตฟอร์มเป้าหมาย ซึ่งมีหน่วยประมวลผลและระบบปฏิบัติการเป็นปัจจัยหลัก โดยตามตารางในหัวข้อก่อนหน้า หลัก ๆ แล้วมีรูปแบบข้อมูลอยู่ 4 รูปแบบ คือ LP32, ILP32, LLP64, และ LP64 ซึ่งหากต้องการหาความหาย L หมายถึง Long, P หมายถึง Pointer, และ I หมายถึง Integer (จำนวนเต็ม) แล้วตามด้วยเลขบิต === ประเภทจำนวนทศนิยมจริง (Real floating types) #h(8.85em) ภาษา C นั้นมีประเภทข้อมูลสำหรับแทนตัวเลขทศนิยมจริง 3 (หรือ 6 ตั้งแต่ C23) ประเภท 1. `float` จำนวนทศนิยมความแม่นยำเดี่ยว ตรงกับฟอร์แมตมาตรฐาน IEEE-754 binary32 หากรองรับ 2. `double` จำนวนทศนิยมความแม่นยำสองเท่า ตรงกับฟอร์แมตมาตรฐาน IEEE-754 binary64 หากรองรับ 3. `long double` จำนวนทศนิยมความแม่นยำเพิ่มเติม ตรงกับฟอร์แมตมาตรฐาน IEEE-754 binary128 หากรองรับ มิฉะนั้นจะตรงกับ IEEE-754 binary64-extended หากรองรับ มิฉะนั้นจะตรงกับรูปแบบจำนวนทศนิยมที่ไม่ตรงกับมาตรฐาน IEEE-754 รูปแบบใดก็ได้ตราบใดที่มีความแม่นยำกว่า binary64 และระยะข้อมูลนั้นอย่างน้อยก็ต้องดีเท่า binary64 และหากไม่รองรับทั้งหมดนั้น จะตรงกับฟอร์แมตมาตรฐาน IEEE-754 binary64 #listy( indent: 10.20em, numbering: thai-numbering, [รูปแบบ binary128 นั้นถูกใช้โดยระบบ HP-UX, SPARC, MIPS, ARM64, และ z/OS บางระบบ], [รูปแบบ IEEE-754 binary64-extended ที่รู้จักกันอย่างแพร่หลายที่สุดคือรูปแบบความแม่นยำเพิ่มเติม 80 บิต x87 ซึ่งถูกใช้โดยสถาปัตยกรรม x86 และ x86-64 บางระบบ#jb (การยกเว้นที่ควรพูดถึงคือ MSVC ที่กำหนดให้ `long double` อยู่ในรูปแบบเดียวกันกับ `double`, เช่น#jb binary64)], ) #h(8.85em) เมื่อใช้มาตรฐาน C ตั้งแต่ C23 เป็นต้นไปและหากแพลตฟอร์มของคุณใช้งานคอนแสตนต์มาโคร `__STDC_IEC_60559_DFP__` ข้อมูลประเภทตัวเลขทศนิยมดังต่อไปนี้จะถูกรองรับด้วย: + `_Decimal32` แทนรูปแบบมาตรฐาน IEEE-754 decimal32 + `_Decimal64` แทนรูปแบบมาตรฐาน IEEE-754 decimal64 + `_Decimal128` แทนรูปแบบมาตรฐาน IEEE-754 decimal128 #h(8.85em) มิฉะนั้น ประเภทตัวเลขทศนิยมเพิ่มเติมเหล่านี้จะไม่ถูกรองรับ #h(8.85em) ข้อมูลประเภททศนิยมอาจรองรับค่าพิเศษเพิ่มเติมได้แก่ 1. อนันต์ (Infinity, ทั้งบวกและลบ) 2. ศูนย์ติดลบ, `-0.0` โดยมีค่าเท่ากับศูยน์ที่ติดบวก แต่อาจมีความหมายในบางสมการ เช่น `1.0 / 0.0 == INFINITY` แต่ `1.0 / -0.0 == -INFINITY` 3. ไม่ใช่ตัวเลข (not-a-number; NaN) ซึ่งไม่เท่ากับอะไรเลย รวมถึงตัวมันเอง #h(8.85em) ทศนิยมจำนวนจริงสามารถถูกใช้กับตัวดำเนินการทางคณิตศาสตร์ได้ *+ - / \** และฟังก์ชันทางคณิตศาสตร์จาก `` โดยทั้งตัวดำเนินการและฟังก์ชันจากไลบรารีนั้นสามารถก่อให้เกิดการแสดงข้อผิดพลาดของจำนวนทศนิยมได้และจะตั้งค่า `errno` === ประเภทจำนวนทศนิยมซับซ้อน (Complex floating types) #h(8.85em) ประเภทข้อมูลจำนวนทศนิยมซับซ้อนนั้นเป็นประเภทที่แทนตัวเลขเชิงซ้อน (complex number) นั้นคือ ตัวเลขที่สามารถถูกเขียนแทนเป็นผลรวมของจำนวนจริงและจำนวนจริงที่คูณด้วยจำนวนจินตภาพ (a + bi) โดยประเภทจำนวนเชิงซ้อนมีอยู่สามประเภท ได้แก่ 1. `float _Complex` (และสามารถใช้ `float complex` ได้เช่นกันหากนำเข้า ``) 2. `double _Complex` (และสามารถใช้ `double complex` ได้เช่นกันหากนำเข้า ``) 3. `long double _Complex` (และสามารถใช้ `long double complex` ได้เช่นกันหากนำเข้า ``) === ประเภทจำนวนทศนิยมจินตภาพ (Imaginary floating types) #h(8.85em) ประเภทข้อมูลจำนวนทศนิยมจินตภาพนั้นเป็นประเภทที่แทนตัวเลขจินตภาพ#jb (imaginary number) นั้นคือ ตัวเลขที่สามารถถูกเขียนแทนเป็นจำนวนจริงที่คูณด้วยจำนวนจินตภาพ #math.equation( $b i$, alt: "b i", ) โดยประเภทจำนวนเชิงซ้อนมีอยู่สามประเภท ได้แก่ 1. `float _Imaginary` (และสามารถใช้ `float imaginary` ได้เช่นกันหากนำเข้า#jb ``) 2. `double _Imaginary` (และสามารถใช้ `double imaginary` ได้เช่นกันหากนำเข้า ``) 3. `long double _Imaginary` (และสามารถใช้ `long double imaginary` ได้เช่นกันหากนำเข้า ``) === ประเภทตัวอักษร (Character) 1. `signed char` คือประเภทสำหรับตัวอักษรแบบ signed 2. `unsigned char` คือประเภทสำหรับตัวอักษรแบบ unsigned 3. `char` คือประเภทสำหรับตัวอักษรแบบไม่ระบุระยะข้อมูล ซึ่งสามารถเท่ากับ#jb `signed char` หรือ `unsigned char` ก็ได้ขึ้นอยู่กับแพลตฟอร์มและคอมไพเลอร์ แต่อย่างไรก็ตาม `char` นั้นไม่ใช่เพียงแค่มาโครที่ลิงก์ไปยังประเภทอื่น ๆ แต่ `char` คือประเภทของมันเอง === คีย์เวิร์ด 1. `bool`, `true`, `false`, `char`, `int`, `short`, `long`, `signed`, `unsigned`, `float`, `double` 2. `_Bool`, `_BitInt`, `_Complex`, `_Imaginary`, `_Decimal32`, `_Decimal64`, `_Decimal128` === ระยะค่าที่เก็บได้ #h(8.85em) ก่อนมาตรฐาน C23 มาตรฐาน C อนุญาตการแทนตัวเลขแบบใดก็ได้ และ#jb ระยะขั้นต่ำของตัวเลข N บิตคือ #math.minus#[(2#super[N-1] #math.minus 1)] ถึง +2#super[N-1] #math.minus 1 (เช่น -127 ถึง 127 สำหรับประเภทตัวเลข 8 บิต) ซึ่งตรงกับขอบเขตของส่วนเติมเต็มหนึ่ง (one's complement) หรือการแทนจำนวนมีเครื่องหมาย (sign-and-magnitude) #h(8.85em) อย่างไรก็ตาม รูปแบบข้อมูลที่ใช้กันอย่างแพร่หลายทั้งหมด (รวมถึง ILP32, LP32, LP64, และ LLP64) และคอมไพเลอร์ C เกือบทั้งหมดใช้การแทนตัวเลขแบบส่วนเติมเต็มสอง#jb (two's complement) (มีข้อยกเว้นที่ทราบแค่บางคอมไพเลอร์สำหรับระบบ UNISYS) และตั้งแต่มาตรฐาน C23 มันคือการแทนตัวเลขแบบเดียวที่ถูกอนุญาตให้ใช้โดยมาตรฐาน และมีขอบเขตที่แน่นอนระหว่าง -2#super[N#math.minus#[1]] ถึง +2#super[N#math.minus#[1]] (เช่น -128 ถึง 127 สำหรับประเภทตัวเลข 8 บิต) #h(8.85em) ตารางต่อไปนี้ให้ข้อมูลเกี่ยวกับขอบเขตของประเภทข้อมูลต่าง ๆ (มีการเพิ่มจุลภาคในทศนิยมเพื่อเพิ่มความสะดวกในการอ่าน) #show table.cell.where(x: 0): strong #show math.equation.where(block: true): set block(spacing: 0.6em) #set enum(indent: 0em) #figure( table( columns: 5, align: horizon + center, table.header( table.cell([ประเภท], rowspan: 2), table.cell([ขนาด\ (บิต)], rowspan: 2), table.cell([รูปแบบ], rowspan: 2), table.cell([ระยะค่า], colspan: 2), [โดยประมาณ], [แน่นอน], ), table.cell([ตัวอักษร], rowspan: 4), table.cell([8], rowspan: 2), [signed], [], [-128 ถึง 127], [unsigned], [], [0 ถึง 255], [16], [UTF-16], [], [0 ถึง 65535], [32], [UTF-32], [], [0 ถึง 1114111 (0x10ffff)], table.cell([จำนวน\ เต็ม], rowspan: 6), table.cell([16], rowspan: 2), [signed], [± 3.27 · 104], [-32768 ถึง 32767], [unsigned], [0 ถึง 6.55 · 104], [0 ถึง 65535], table.cell([32], rowspan: 2), [signed], [± 2.14 · 109], [-2,147,483,648 ถึง 2,147,483,647], [unsigned], [0 ถึง 4.29 · 109], [0 ถึง 4,294,967,295], table.cell([64], rowspan: 2), [signed], [± 9.22 · 1018], [-9,223,372,036,854,775,808 ถึง 9,223,372,036,854,775,807], [unsigned], [0 ถึง 1.84 · 1019], [0 ถึง 18,446,744,073,709,551,615], table.cell([ทศนิยม\ ไบนารี], rowspan: 2), [32], [IEEE-754], table.cell( [ + min subnormal: #math.equation( $± 1.401,298,4 · 10^(-45)$, alt: "บวกลบ 1.4012984 คูณ 10 ยกกำลัง -45", ) + min normal: #math.equation( $± 1.175,494,3 · 10^(-38)$, alt: "บวกลบ 1.1754943 คูณ 10 ยกกำลัง -38", ) + max: \ #math.equation( $± 3.402,823,4 · 10^(38)$, alt: "บวกลบ 3.4028234 คูณ 10 ยกกำลัง 38", ) ], align: left, ), table.cell( [ + min subnormal:\ `±0x1p-149` + min normal:\ `±0x1p-126` + max:\ `±0x1.fffffep+127` ], align: left, ), [64], [IEEE-754], table.cell( [ + min subnormal: #math.equation( $± 4.940,656,458,412\ · 10^(-324)$, alt: "บวกลบ 4.940656458412 คูณ 10 ยกกำลัง ลบ 324", block: true, ) + min normal: #math.equation( $± 2.225,073,858,507,201,\ 4 · 10^(-308)$, alt: "บวกลบ 2.2250738585072014 คูณ 10 ยกกำลัง ลบ 308", block: true, ) + max: #math.equation( $± 1.797,693,134,862,315,\ 7 · 10^308$, alt: "บวกลบ 1.7976931348623157 คูณ 10 ยกกำลัง 308", block: true, ) ], align: left, ), table.cell( [ + min subnormal: `±0x1p-1074` + min normal:\ `±0x1p-1022` + max: `±0x1` \ `.fffffffffffffp+1023` ], align: left, ), ), caption: [ตารางแสดงขอบเขตประเภทข้อมูล], ) #pagebreak() #figure( table( columns: 5, align: horizon + center, table.header( table.cell([ประเภท], rowspan: 2), table.cell([ขนาด\ (บิต)], rowspan: 2), table.cell([รูปแบบ], rowspan: 2), table.cell([ระยะค่า], colspan: 2), [โดยประมาณ], [แน่นอน], ), table.cell([ทศนิยม\ ไบนารี], rowspan: 2), [80], [x86], table.cell( [ + min subnormal: #math.equation( $± 3.645,199,531,882,474,\ 602,528 · 10^(-4951)$, alt: "บวกลบ 3.645199531882474602528 คูณ 10 ยกกำลัง ลบ 4951", block: true, ) + min normal: #math.equation( $± 3.362,103,143,112,093,\ 506,263 · 10^(-4932)$, alt: "บวกลบ 3.362103143112093506263 คูณ 10 ยกกำลัง ลบ 4932", block: true, ) + max: #math.equation( $± 1.189,731,495,357,231,\ 765,021 · 10^(4932)$, alt: "บวกลบ 1.189731495357231765021 คูณ 10 ยกกำลัง 4932", block: true, ) ], align: left, ), table.cell( [ + min subnormal: `±0x1p-16445` + min normal: `±0x1p-16382` + max: `±0x1.ffffffff`\ `fffffffep+16383` ], align: left, ), [128], [IEEE-754], table.cell( [ + min subnormal: #math.equation( $± 6.475,175,119,438,025,\ 110,924,438,958,227,\ 646,552,5 · 10^(-4966)$, alt: "บวกลบ 6.4751751194380251109244389582276465525 คูณ 10 ยกกำลัง ลบ 4966", block: true, ) + min normal: #math.equation( $± 3.362,103,143,112,093,\ 506,262,677,817,321,\ 752,602,6 · 10^(-4932)$, alt: "บวกลบ 3.3621031431120935062626778173217526026 คูณ 10 ยกกำลัง ลบ 4932", block: true, ) + max: #math.equation( $± 1.189,731,495,357,231,\ 765,085,759,326,628,\ 007,016,2 · 10^4932$, alt: "บวกลบ 1.1897314953572317650857593266280070162 คูณ 10 ยกกำลัง 4932", block: true, ) ], align: left, ), table.cell( [ + min subnormal: `±0x1p-16494` + min normal: `±0x1p-16382` + max: `±0x1.ffffffffffffff`\ `ffffffffffffffp+16383` ], align: left, ), table.cell([ทศนิยม\ เดซิมอล], rowspan: 3), [32], [IEEE-754], [], table.cell( [ + min subnormal:\ #math.equation($± 1 · 10^(-101)$, alt: "บวกลบ 1 คูณ 10 ยกกำลัง ลบ 101") + min normal:\ #math.equation($± 1 · 10^(-95)$, alt: "บวกลบ 1 คูณ 10 ยกกำลัง ลบ 95") + max:\ #math.equation( $± 9.999'999 · 10^96$, alt: "บวกลบ 9.999999 คูณ 10 ยกกำลัง 96", ) ], align: left, ), [64], [IEEE-754], [], table.cell( [ + min subnormal:\ #math.equation($± 1 · 10^(-398)$, alt: "บวกลบ 1 คูณ 10 ยกกำลัง ลบ -398") + min normal:\ #math.equation($± 1 · 10^(-383)$, alt: "บวกลบ 1 คูณ 10 ยกกำลัง ลบ 383") + max: #math.equation( $± 9.999'999'999'999'999\ · 10^384$, alt: "บวกลบ 9.999999999999999 คูณ 10 ยกกำลัง 384", block: true, ) ], align: left, ), [128], [IEEE-754], [], table.cell( [ + min subnormal:\ #math.equation( $± 1 · 10^(-6176)$, alt: "บวกลบ 1 คูณ 10 ยกกำลัง ลบ 6176", ) + min normal:\ #math.equation( $± 1 · 10^(-6143)$, alt: "บวกลบ 1 คูณ 10 ยกกำลัง ลบ 6143", ) + max: #math.equation( $ ± 9.999'999'999'999'999'\ 999'999'999'999'999'999\ · 10^6144 $, alt: "บวกลบ 9.999999999999999999999999999999999 คูณ 10 ยกกำลัง 6144", block: true, ) ], align: left, ), ), caption: [ตารางแสดงขอบเขตประเภทข้อมูล (ต่อ)], ) #set enum(indent: 1em) == ชุดแปลโปรแกรมของกนู (GNU Compiler Collection; GCC) #h(5.05em) ในกระบวนการการพัฒนาโครงงานนี้ ชุดแปลโปรแกรมของกนูนั้นถูกใช้เป็นหลักเนื่องจากเป็นชุดแปลโปรแกรม (คอมไพเลอร์; Compiler) ที่ใช้เป็นหลักในการพัฒนาโคดที่สร้างบนพื้นฐาน Arduino และบอร์ดต่าง ๆ รวมถึงบอร์ด ESP32 #h(5.05em) ชุดคอมไพเลอร์ GNU (GNU Compiler Collection; GCC) (เดิมชื่อ GNU C Compiler) คือชุดคอมไพเลอร์จากโครงการ GNU ที่รองรับภาษาโปรแกรม สถาปัตยกรรมฮาร์ดแวร์ และระบบปฏิบัติการต่าง ๆ มูลนิธิซอฟต์แวร์เสรี (FSF) เผยแพร่ GCC ในฐานะซอฟต์แวร์เสรีภายใต้สัญญาอนุญาตสถูกเรียกาธารณะทั่วไปของ GNU (GNU GPL) GCC เป็นองค์ประกอบสำคัญของชุดเครื่องมือ GNU ซึ่งใช้สำหรับโครงการส่วนใหญ่ที่เกี่ยวข้องกับ GNU และเคอร์เนล Linux ด้วยโคดประมาณ 15 ล้านบรรทัดในปี 2019 GCC จึงเป็นหนึ่งในโปรแกรมฟรีที่ใหญ่ที่สุดเท่าที่เคยมีมา GCC มีบทบาทสำคัญในการเติบโตของซอฟต์แวร์เสรี ทั้งในฐานะเครื่องมือและตัวอย่าง #h(5.05em) นอกจากจะเป็นคอมไพเลอร์อย่างเป็นทางการของระบบปฏิบัติการ GNU แล้ว GCC ยังได้รับการยอมรับให้เป็นคอมไพเลอร์มาตรฐานโดยระบบปฏิบัติการคอมพิวเตอร์สมัยใหม่ที่คล้ายกับ Unix อื่นๆ อีกมากมาย รวมถึงระบบปฏิบัติการ Linux ส่วนใหญ่ ระบบปฏิบัติการตระกูล BSD ส่วนใหญ่ก็เปลี่ยนมาใช้ GCC ไม่นานหลังจากเปิดตัว แม้ว่าหลังจากนั้น FreeBSD และ Apple macOS ได้เปลี่ยนมาใช้คอมไพเลอร์ Clang ส่วนใหญ่เป็นเพราะเหตุผลด้านลิขสิทธิ์ GCC ยังสามารถคอมไพเลอร์โคดสำหรับระบบปฏิบัติการ Windows, Android, iOS, Solaris, HP-UX, AIX และ MS-DOS ได้อีกด้วย #h(5.05em) GCC ได้รับการพอร์ตไปยังแพลตฟอร์มและสถาปัตยกรรมชุดคำสั่งต่าง ๆ มากกว่าคอมไพเลอร์อื่น ๆ และถูกนำไปใช้งานอย่างกว้างขวางในฐานะเครื่องมือในการพัฒนาซอฟต์แวร์ทั้งแบบฟรีและแบบที่เป็นกรรมสิทธิ์ นอกจากนี้ GCC ยังพร้อมใช้งานสำหรับระบบฝังตัวมากมาย รวมถึงชิปที่ใช้ ARM และ Power ISA