วันพฤหัสบดีที่ 7 พฤษภาคม พ.ศ. 2558

ภาษาซี

 ภาษาซี
Text in light blue serif capital letters on white background and very large light blue sans-serif letter C.
ภาษาซี (C) เป็นภาษาโปรแกรมสำหรับวัตถุประสงค์ทั่วไป เริ่มพัฒนาขึ้นระหว่าง พ.ศ. 2512-2516 (ค.ศ. 1969-1973) โดยเดนนิส ริชชี่ (Denis Retchie) ที่เอทีแอนด์ทีเบลล์แล็บส์ (AT&T Bell Labs) [4][5] ภาษาซีมีเครื่องมืออำนวยความสะดวกสำหรับการเขียนโปรแกรมเชิงโครงสร้างและอนุญาตให้มีขอบข่ายตัวแปร (scope) และการเรียกซ้ำ (recursion) ในขณะที่ระบบชนิดตัวแปรอพลวัตก็ช่วยป้องกันการดำเนินการที่ไม่ตั้งใจหลายอย่าง เหมือนกับภาษาโปรแกรมเชิงคำสั่งส่วนใหญ่ในแบบแผนของภาษาอัลกอล การออกแบบของภาษาซีมีคอนสตรักต์ (construct) ที่โยงกับชุดคำสั่งเครื่องทั่วไปได้อย่างพอเพียง จึงทำให้ยังมีการใช้ในโปรแกรมประยุกต์ซึ่งแต่ก่อนลงรหัสเป็นภาษาแอสเซมบลี คือซอฟต์แวร์ระบบอันโดดเด่นอย่างระบบปฏิบัติการคอมพิวเตอร์ ยูนิกซ์ [6]
ภาษาซีเป็นภาษาโปรแกรมหนึ่งที่ใช้กันอย่างแพร่หลายมากที่สุดตลอดกาล [7][8] และตัวแปลโปรแกรมของภาษาซีมีให้ใช้งานได้สำหรับสถาปัตยกรรมคอมพิวเตอร์และระบบปฏิบัติการต่าง ๆ เป็นส่วนมาก
ภาษาหลายภาษาในยุคหลังได้หยิบยืมภาษาซีไปใช้ทั้งทางตรงและทางอ้อม ตัวอย่างเช่น ภาษาดี ภาษาโก ภาษารัสต์ ภาษาจาวาจาวาสคริปต์ ภาษาลิมโบ ภาษาแอลพีซี ภาษาซีชาร์ป ภาษาอ็อบเจกทีฟ-ซี ภาษาเพิร์ล ภาษาพีเอชพี ภาษาไพทอน ภาษาเวอริล็อก(ภาษาพรรณนาฮาร์ดแวร์) [3] และซีเชลล์ของยูนิกซ์ ภาษาเหล่านี้ได้ดึงโครงสร้างการควบคุมและคุณลักษณะพื้นฐานอื่น ๆ มาจากภาษาซี ส่วนใหญ่มีวากยสัมพันธ์คล้ายคลึงกับภาษาซีเป็นอย่างมากโดยรวม (ยกเว้นภาษาไพทอนที่ต่างออกไปอย่างสิ้นเชิง) และตั้งใจที่จะผสานนิพจน์และข้อความสั่งที่จำแนกได้ของวากยสัมพันธ์ของภาษาซี ด้วยระบบชนิดตัวแปร ตัวแบบข้อมูล และอรรถศาสตร์ที่อาจแตกต่างกันโดยมูลฐาน ภาษาซีพลัสพลัสและภาษาอ็อบเจกทีฟ-ซีเดิมเกิดขึ้นในฐานะตัวแปลโปรแกรมที่สร้างรหัสภาษาซี ปัจจุบันภาษาซีพลัสพลัสแทบจะเป็นเซตใหญ่ของภาษาซี [9] ในขณะที่ภาษาอ็อบเจกทีฟ-ซีก็เป็นเซตใหญ่อันเคร่งครัดของภาษาซี [10]
ก่อนที่จะมีมาตรฐานภาษาซีอย่างเป็นทางการ ผู้ใช้และผู้พัฒนาต่างก็เชื่อถือในข้อกำหนดอย่างไม่เป็นทางการในหนังสือที่เขียนโดยเดนนิส ริตชี และไบรอัน เคอร์นิกัน (Brian Kernighan) ภาษาซีรุ่นนั้นจึงเรียกกันโดยทั่วไปว่า ภาษาเคแอนด์อาร์ซี (K&R C) ต่อมา พ.ศ. 2532 สถาบันมาตรฐานแห่งชาติของสหรัฐอเมริกา (ANSI) ได้ตีพิมพ์มาตรฐานสำหรับภาษาซีขึ้นมา เรียกกันว่า ภาษาแอนซีซี(ANSI C) หรือ ภาษาซี89 (C89) ในปีถัดมา องค์การระหว่างประเทศว่าด้วยการมาตรฐาน (ISO) ได้อนุมัติให้ข้อกำหนดเดียวกันนี้เป็นมาตรฐานสากล เรียกกันว่า ภาษาซี90 (C90) ในเวลาต่อมาอีก องค์การฯ ก็ได้เผยแพร่ส่วนขยายมาตรฐานเพื่อรองรับสากลวิวัตน์(internationalization) เมื่อ พ.ศ. 2538 และมาตรฐานที่ตรวจชำระใหม่เมื่อ พ.ศ. 2542 เรียกกันว่า ภาษาซี99 (C99) มาตรฐานรุ่นปัจจุบันก็ได้รับอนุมัติเมื่อเดือนธันวาคม พ.ศ. 2554 เรียกกันว่า ภาษาซี11 (C11)
การออกแบบ
ภาษาซีเป็นภาษาที่ใช้ในการมีปฏิสัมพันธ์เช่น เชิงคำสั่ง (หรือเชิงกระบวนงาน) ถูกออกแบบขึ้นเพื่อใช้แปลด้วยตัวแปลโปรแกรมแบบการเชื่อมโยงที่ตรงไปตรงมา สามารถเข้าถึงหน่วยความจำในระดับล่าง เพื่อสร้างภาษาที่จับคู่อย่างมีประสิทธิภาพกับชุดคำสั่งเครื่อง และแทบไม่ต้องการสนับสนุนใด ๆ ขณะทำงาน ภาษาซีจึงเป็นประโยชน์สำหรับหลายโปรแกรมที่ก่อนหน้านี้เคยเขียนในภาษาแอสเซมบลีมาก่อน หากคำนึงถึงความสามารถในระดับล่าง ภาษานี้ถูกออกแบบขึ้นเพื่อส่งเสริมการเขียนโปรแกรมที่ขึ้นอยู่กับเครื่องใดเครื่องหนึ่ง (machine-independent) โปรแกรมภาษาซีที่เขียนขึ้นตามมาตรฐานและเคลื่อนย้ายได้ สามารถแปลได้บนแพลตฟอร์มคอมพิวเตอร์และระบบปฏิบัติการต่าง ๆ อย่างกว้างขวาง โดยแก้ไขรหัสต้นฉบับเพียงเล็กน้อยหรือไม่ต้องแก้ไขเลย ภาษานี้สามารถใช้ได้บนแพลตฟอร์มได้หลากหลายตั้งแต่ไมโครคอนโทรลเลอร์ฝังตัวไปจนถึงซูเปอร์คอมพิวเตอร์
ลักษณะเฉพาะ
ภาษาซีมีสิ่งอำนวยสำหรับการเขียนโปรแกรมเชิงโครงสร้าง และสามารถกำหนดขอบข่ายตัวแปรและเรียกซ้ำ เช่นเดียวกับภาษาโปรแกรมเชิงคำสั่งส่วนใหญ่ในสายตระกูลภาษาอัลกอล ในขณะที่ระบบชนิดตัวแปรแบบอพลวัตช่วยป้องกันการดำเนินการที่ไม่ได้ตั้งใจ รหัสที่ทำงานได้ทั้งหมดในภาษาซีถูกบรรจุอยู่ในฟังก์ชัน พารามิเตอร์ของฟังก์ชันส่งผ่านด้วยค่าของตัวแปรเสมอ ส่วนการส่งผ่านด้วยการอ้างอิงจะถูกจำลองขึ้นโดยการส่งผ่านค่าตัวชี้ ชนิดข้อมูลรวมแบบแตกต่าง (struct) ช่วยให้สมาชิกข้อมูลที่เกี่ยวข้องกันสามารถรวมกันและจัดการได้ในหน่วยเดียว รหัสต้นฉบับของภาษาซีเป็นรูปแบบอิสระ ซึ่งใช้อัฒภาค (;) เป็นตัวจบคำสั่ง (มิใช่ตัวแบ่ง)
ภาษาซียังมีลักษณะเฉพาะต่อไปนี้เพิ่มเติม
ตัวแปรอาจถูกซ่อนในบล็อกซ้อนใน
ชนิดตัวแปรไม่เคร่งครัด เช่นข้อมูลตัวอักษรสามารถใช้เป็นจำนวนเต็ม
เข้าถึงหน่วยความจำคอมพิวเตอร์ในระดับต่ำโดยแปลงที่อยู่ในเครื่องด้วยชนิดตัวแปรตัวชี้ (pointer)
ฟังก์ชันและตัวชี้ข้อมูลรองรับการทำงานในภาวะหลายรูปแบบ (polymorphism)
การกำหนดดัชนีแถวลำดับสามารถทำได้ด้วยวิธีรอง คือนิยามในพจน์ของเลขคณิตของตัวชี้
ตัวประมวลผลก่อนสำหรับการนิยามแมโคร การรวมไฟล์รหัสต้นฉบับ และการแปลโปรแกรมแบบมีเงื่อนไข
ความสามารถที่ซับซ้อนเช่น ไอ/โอ การจัดการสายอักขระ และฟังก์ชันทางคณิตศาสตร์ รวมอยู่ในไลบรารี
คำหลักที่สงวนไว้มีจำนวนค่อนข้างน้อย
ตัวดำเนินการแบบประสมจำนวนมาก อาทิ +=, -=, *=, ++ ฯลฯ
โครงสร้างการเขียน คล้ายภาษาบีมากกว่าภาษาอัลกอล ตัวอย่างเช่น
ใช้วงเล็บปีกกา { ... } แทนที่จะเป็น begin ... end ในภาษาอัลกอล 60 หรือวงเล็บโค้ง ( ... ) ในภาษาอัลกอล 68
เท่ากับ = ใช้สำหรับกำหนดค่า (คัดลอกข้อมูล) เหมือนภาษาฟอร์แทรน แทนที่จะเป็น := ในภาษาอัลกอล
เท่ากับสองตัว == ใช้สำหรับเปรียบเทียบความเท่ากัน แทนที่จะเป็น .EQ. ในภาษาฟอร์แทรนหรือ = ในภาษาเบสิกและภาษาอัลกอล
ตรรกะ "และ" กับ "หรือ" แทนด้วย && กับ || ตามลำดับ แทนที่จะเป็นตัวดำเนินการ ∧ กับ ∨ ในภาษาอัลกอล แต่ตัวดำเนินการดังกล่าวจะไม่ประเมินค่าตัวถูกดำเนินการทางขวา ถ้าหากผลลัพธ์จากทางซ้ายสามารถพิจารณาได้แล้ว เหตุการณ์เช่นนี้เรียกว่าการประเมินค่าแบบลัดวงจร (short-circuit evaluation) และตัวดำเนินการดังกล่าวก็มีความหมายต่างจากตัวดำเนินการระดับบิต & กับ |
คุณลักษณะที่ขาดไป
ธรรมชาติของภาษาในระดับต่ำช่วยให้โปรแกรมเมอร์ควบคุมสิ่งที่คอมพิวเตอร์กระทำได้อย่างใกล้ชิด ในขณะที่อนุญาตให้มีการปรับแต่งพิเศษและการทำให้เหมาะที่สุดสำหรับแพลตฟอร์มหนึ่งใดโดยเฉพาะ สิ่งนี้ทำให้รหัสสามารถทำงานได้อย่างมีประสิทธิภาพบนฮาร์ดแวร์ที่มีทรัพยากรจำกัดมาก ๆ ได้เช่นระบบฝังตัว
ภาษาซีไม่มีคุณลักษณะบางอย่างที่มีในภาษาอื่นอาทิ
ไม่มีการนิยามฟังก์ชันซ้อนใน
ไม่มีการกำหนดค่าแถวลำดับหรือสายอักขระโดยตรง (การคัดลอกข้อมูลจะกระทำผ่านฟังก์ชันมาตรฐาน แต่ก็รองรับการกำหนดค่าวัตถุที่มีชนิดเป็น struct หรือ union)
ไม่มีการเก็บข้อมูลขยะโดยอัตโนมัติ
ไม่มีข้อกำหนดเพื่อการตรวจสอบขอบเขตของแถวลำดับ
ไม่มีการดำเนินการสำหรับแถวลำดับทั้งชุดในระดับตัวภาษา
ไม่มีวากยสัมพันธ์สำหรับช่วงค่า (range) เช่น A..B ที่ใช้ในบางภาษา
ก่อนถึงภาษาซี99 ไม่มีการแบ่งแยกชนิดข้อมูลแบบบูล (ค่าศูนย์หรือไม่ศูนย์ถูกนำมาใช้แทน) [12]
ไม่มีส่วนปิดคลุมแบบรูปนัย (closure) หรือฟังก์ชันในรูปแบบพารามิเตอร์ (มีเพียงตัวชี้ของฟังก์ชันและตัวแปร)
ไม่มีตัวสร้างและโครูทีน การควบคุมกระแสการทำงานภายในเทร็ดมีเพียงการเรียกใช้ฟังก์ชันซ้อนลงไป เว้นแต่การใช้ฟังก์ชัน longjmp หรือ setcontext จากไลบรารี
ไม่มีการจัดกระทำสิ่งผิดปรกติ (exception handling) ฟังก์ชันไลบรารีมาตรฐานจะแสดงเงื่อนไขข้อผิดพลาดด้วยตัวแปรส่วนกลาง errno และ/หรือค่ากลับคืนพิเศษ และฟังก์ชันไลบรารีได้เตรียม goto แบบไม่ใช่เฉพาะที่ไว้ด้วย
การเขียนโปรแกรมเชิงมอดูลรองรับแค่ระดับพื้นฐานเท่านั้น
การโอเวอร์โหลดฟังก์ชันหรือตัวดำเนินการไม่รองรับภาวะหลายรูปแบบขณะแปลโปรแกรม
การเขียนโปรแกรมเชิงวัตถุรองรับในระดับที่จำกัดมาก โดยพิจารณาจากภาวะหลายรูปแบบกับการรับทอด (inheritance)
การซ่อนสารสนเทศ (encapsulation) รองรับในระดับที่จำกัด
ไม่รองรับโดยพื้นฐานกับการทำงานแบบมัลติเทร็ดและเครือข่ายคอมพิวเตอร์
ไม่มีไลบรารีมาตรฐานสำหรับคอมพิวเตอร์กราฟิกส์และความจำเป็นหลายอย่างในการเขียนโปรแกรมประยุกต์
คุณลักษณะเหล่านี้จำนวนหนึ่งมีให้ใช้ได้จากส่วนขยายในตัวแปลโปรแกรมบางตัว หรือจัดสรรไว้แล้วในสภาพแวดล้อมของระบบปฏิบัติการ (เช่นโพสซิกซ์) หรือจัดเตรียมโดยไลบรารีภายนอก หรือสามารถจำลองโดยดัดแปลงแก้ไขรหัสที่มีอยู่ หรือบางครั้งก็ถูกพิจารณาว่าไม่ใช่รูปแบบการเขียนโปรแกรมที่เหมาะสม
พฤติกรรมไม่นิยาม
การดำเนินการหลายอย่างในภาษาซีมีพฤติกรรมไม่นิยามซึ่งไม่ถูกกำหนดว่าต้องตรวจสอบขณะแปลโปรแกรม ในกรณีของภาษาซี "พฤติกรรมไม่นิยาม" หมายถึงพฤติกรรมเฉพาะอย่างที่เกิดขึ้นโดยมาตรฐานมิได้ระบุไว้ และสิ่งที่จะเกิดขึ้นก็ไม่มีในเอกสารการใช้งานของภาษาซี หนึ่งในชุดคำสั่งที่มีชื่อเสียงและน่าขบขันจากกลุ่มข่าว comp.std.c และ comp.lang.c นั้นทำให้โปรแกรมเกิดปัญหาที่เรียกว่า "ปิศาจที่ออกมาจากจมูกของคุณ" (demons to fly out of your nose) [13] บางครั้งสิ่งที่เกิดขึ้นในทางปฏิบัติอันเป็นผลมาจากพฤติกรรมไม่นิยามทำให้เกิดจุดบกพร่องที่ยากต่อการตรวจสอบและอาจทำให้ข้อมูลในหน่วยความจำผิดแปลกไป ตัวแปลโปรแกรมบางชนิดช่วยสร้างการดำเนินงานที่ทำให้พฤติกรรมนั้นดีขึ้นและมีเหตุผล ซึ่งแตกต่างจากการแปลโดยตัวแปลชนิดอื่นที่อาจดำเนินงานไม่เหมือนกัน สาเหตุที่พฤติกรรมบางอย่างยังคงไว้ว่าไม่นิยามก็เพื่อให้ตัวแปลโปรแกรมบนสถาปัตยกรรมชุดของคำสั่งเครื่องที่หลากหลาย สามารถสร้างรหัสที่ทำงานได้ในพฤติกรรมที่นิยามอย่างมีประสิทธิภาพมากขึ้น ซึ่งเชื่อว่าเป็นบทบาทหนึ่งที่สำคัญของภาษาซีในฐานะภาษาสำหรับสร้างระบบ ดังนั้นภาษาซีจึงส่งผลให้เกิดความรับผิดชอบของโปรแกรมเมอร์เพื่อหลีกเลี่ยงพฤติกรรมไม่นิยาม โดยอาจใช้เครื่องมือต่าง ๆ เพื่อค้นหาส่วนของโปรแกรมว่าพฤติกรรมใดบ้างที่ไม่นิยาม ตัวอย่างของพฤติกรรมไม่นิยามเช่น
การเข้าถึงข้อมูลนอกขอบเขตของแถวลำดับ
ข้อมูลล้น (overflow) ในตัวแปรจำนวนเต็มมีเครื่องหมาย
ฟังก์ชันที่กำหนดไว้ว่าต้องส่งค่ากลับ แต่ไม่มีคำสั่งส่งกลับ (return) ในฟังก์ชัน ในขณะเดียวกันค่าส่งกลับก็ถูกใช้งานด้วย
การอ่านค่าตัวแปรโดยที่ยังไม่ได้กำหนดค่าเริ่มต้น
การดำเนินการเหล่านี้ทั้งหมดเป็นข้อผิดพลาดในการเขียนโปรแกรม ซึ่งสามารถปรากฏในการใช้ภาษาโปรแกรมอื่น ๆ จำนวนมาก ภาษาซีจึงถูกวิพากษ์วิจารณ์เพราะมาตรฐานของมันสามารถชี้ให้เห็นถึงพฤติกรรมไม่นิยามในหลายกรณีได้อย่างชัดเจน รวมไปถึงพฤติกรรมบางอย่างที่อาจนิยามไว้อย่างดีแล้ว และไม่มีการระบุกลไกการจัดกระทำต่อข้อผิดพลาดขณะทำงานเลย
ตัวอย่างหนึ่งของพฤติกรรมไม่นิยามเช่นการเรียกใช้ fflush() บนกระแสข้อมูลป้อนเข้า ซึ่งไม่จำเป็นว่าจะทำให้โปรแกรมทำงานผิดพลาด แต่ในบางกรณีที่การทำให้เกิดผลที่สอดคล้องกันได้นิยามไว้แล้วอย่างดี มีความหมายซึ่งใช้ประโยชน์ได้ (จากตัวอย่างนี้คือการสมมติให้ข้อมูลที่ป้อนเข้าถูกละทิ้งทั้งหมดจนถึงอักขระขึ้นบรรทัดใหม่ตัวถัดไป) เป็น ส่วนขยาย ที่อนุญาต ส่วนขยายที่ไม่เป็นมาตรฐานเช่นนี้เป็นข้อจำกัดความสามารถในการเคลื่อนย้ายของซอฟต์แวร์

       ภาษาเคแอนด์อาร์ซี


มื่อ พ.ศ. 2521 ไบรอัน เคอร์นิกัน (Brian Kernighan) และเดนนิส ริตชี ได้ตีพิมพ์หนังสือเล่มแรกชื่อ เดอะซีโปรแกรมมิงแลงกวิจ (The C Programming Language) [14] ซึ่งเป็นที่รู้จักในกลุ่มโปรแกรมเมอร์ภาษาซีว่า "เคแอนด์อาร์" (K&R อักษรย่อของผู้แต่งทั้งสอง) หนังสือเล่มนี้ทำหน้าที่เป็นข้อกำหนดของภาษาอย่างไม่เป็นทางการมาหลายปี ภาษาซีรุ่นดังกล่าวจึงมักถูกอ้างถึงว่าเป็น ภาษาเคแอนด์อาร์ซี (K&R C) ส่วนหนังสือที่ปรับปรุงครั้งที่สองครอบคลุมมาตรฐานแอนซีซีที่มีขึ้นทีหลัง [15]

ภาษาเคแอนด์อาร์ซีได้แนะนำคุณลักษณะหลายประการเช่น

ไลบรารีไอ/โอมาตรฐาน
ชนิดข้อมูล long int (จำนวนเต็มขนาดยาว)
ชนิดข้อมูล unsigned int (จำนวนเต็มไม่มีเครื่องหมาย)
ตัวดำเนินการกำหนดค่าแบบประสมในรูปแบบ =ตัวดำเนินการ (เช่น =-) ถูกเปลี่ยนเป็น ตัวดำเนินการ= (เช่น -=) เพื่อลดปัญหาความกำกวมเชิงความหมาย อย่างเช่นกรณี i=-10 ซึ่งจะถูกตีความว่า i =- 10 แทนที่จะเป็นอย่างที่ตั้งใจคือ i = -10
แม้ว่าหลังจากการเผยแพร่มาตรฐานของภาษาซีเมื่อ พ.ศ. 2532 ภาษาเคแอนด์อาร์ซีถูกพิจารณาว่าเป็น "ส่วนร่วมต่ำสุด" อยู่เป็นเวลาหลายปี (ความสามารถในการแปลรหัสจำนวนหนึ่งเป็นคำสั่งซึ่งทำงานได้บนเครื่องใดก็ตามเป็นอย่างน้อย) ซึ่งโปรแกรมเมอร์ภาษาซีต้องจำกัดความสามารถของพวกเขาในกรณีที่ต้องการให้ระบบสามารถใช้ได้กับหลายเครื่องมากที่สุด เนื่องจากตัวแปลโปรแกรมเก่า ๆ ก็ยังคงมีการใช้งานอยู่ และการเขียนภาษาซีแบบเคแอนด์อาร์อย่างระมัดระวังสามารถเข้ากันได้กับภาษาซีมาตรฐานเป็นอย่างดี

ในภาษาซีรุ่นแรก ๆ เฉพาะฟังก์ชันที่คืนค่าไม่เป็นจำนวนเต็ม จำเป็นต้องประกาศไว้ก่อนการนิยามฟังก์ชันหากมีการเรียกใช้ อีกนัยหนึ่งคือ ฟังก์ชันที่ถูกเรียกใช้โดยไม่มีการประกาศมาก่อน ถือว่าฟังก์ชันนั้นจะคืนค่าเป็นจำนวนเต็มหากค่าของมันถูกใช้งาน ตัวอย่างเช่น

long int SomeFunction();
/* int OtherFunction(); */
/* int */ CallingFunction()
{
    long int test1;
    register /* int */ test2;
    test1 = SomeFunction();
    if (test1 > 0)
        test2 = 0;
    else
        test2 = OtherFunction();
    return test2;
}
จากตัวอย่างข้างต้น การประกาศ int ที่ถูกคัดออก สามารถละเว้นได้ในภาษาเคแอนด์อาร์ซี แต่ long int จำเป็นต้องประกาศ

การประกาศฟังก์ชันของภาษาเคแอนด์อาร์ซีไม่มีการระบุข้อมูลเกี่ยวกับอาร์กิวเมนต์ที่ใช้ ดังนั้นจึงไม่มีการตรวจชนิดข้อมูลพารามิเตอร์ของฟังก์ชัน แม้ว่าตัวแปลโปรแกรมบางตัวจะแสดงข้อความเตือน ถ้าฟังก์ชันถูกเรียกใช้ภายในโดยมีจำนวนอาร์กิวเมนต์ที่ผิด หรือถ้าฟังก์ชันถูกเรียกใช้หลายครั้งจากภายนอกโดยมีชนิดข้อมูลของอาร์กิวเมนต์ต่างกัน เครื่องมือภายนอกอาทิ ลินต์ (lint) ของยูนิกซ์ถูกพัฒนาขึ้นเพื่อให้สามารถตรวจสอบความคงเส้นคงวาของฟังก์ชันที่ใช้งานข้ามไฟล์รหัสต้นฉบับหลายไฟล์

หลายปีถัดจากการเผยแพร่ภาษาเคแอนด์อาร์ซี คุณลักษณะที่ไม่เป็นทางการหลายอย่างก็ถูกเพิ่มเข้ามาในภาษา ซึ่งรองรับโดยตัวแปลโปรแกรมจากเอทีแอนด์ทีและผู้ผลิตรายอื่น คุณลักษณะที่เพิ่มเหล่านี้เช่น

ฟังก์ชัน void
ฟังก์ชันที่คืนค่าเป็นชนิดข้อมูล struct หรือ union (แทนที่จะเป็นตัวชี้)
การกำหนดค่าให้กับชนิดข้อมูล struct
ชนิดข้อมูลแจงนับ (enumerated type)
ส่วนขยายที่เพิ่มขึ้นอย่างมากและการขาดข้อตกลงในเรื่องไลบรารีมาตรฐาน อีกทั้งความนิยมในภาษาและข้อเท็จจริงที่ว่าไม่เพียงแต่ตัวแปลโปรแกรมยูนิกซ์เท่านั้นที่พัฒนาขึ้นตามข้อกำหนดของเคแอนด์อาร์ ทั้งหมดนำไปสู่ความสำคัญของการทำให้เป็นมาตรฐาน
          ภาษาแอนซีซีและภาษาไอโซซี

           ช่วงพุทธทศวรรษ 2520 ภาษาซีหลายรุ่นถูกพัฒนาขึ้นสำหรับเมนเฟรมคอมพิวเตอร์ มินิคอมพิวเตอร์ และไมโครคอมพิวเตอร์อย่างกว้างขวางรวมทั้งไอบีเอ็มพีซี ซึ่งความนิยมของมันเริ่มเพิ่มขึ้นอย่างมีนัยสำคัญ

          เมื่อ พ.ศ. 2526 สถาบันมาตรฐานแห่งชาติของสหรัฐอเมริกา (ANSI) ได้ก่อตั้งคณะกรรมการ เอกซ์3เจ11 ขึ้นมาเพื่อกำหนดมาตรฐานของภาษาซี ต่อมา พ.ศ. 2532 มาตรฐานดังกล่าวได้รับการอนุมัติเป็น ANSI X3.159-1989 "Programming Language C" ซึ่งภาษารุ่นนี้มักถูกอ้างถึงว่าเป็นภาษาแอนซีซี (ANSI C) ภาษาซีมาตรฐาน หรือภาษาซี89 (C89) ในบางครั้ง

         เมื่อ พ.ศ. 2533 องค์การระหว่างประเทศว่าด้วยการมาตรฐาน (ISO) ได้รับเอามาตรฐานแอนซีซี (พร้อมการเปลี่ยนแปลงการจัดรูปแบบ) มาเป็น ISO/IEC 9899:1990 ซึ่งบางครั้งก็ถูกเรียกว่าภาษาไอโซซี (ISO C) หรือภาษาซี90 (C90) ดังนั้นคำว่า "ซี89" กับ "ซี90" จึงหมายถึงภาษาโปรแกรมเดียวกัน

           แอนซีไม่ได้พัฒนามาตรฐานภาษาซีโดยเอกเทศอีกต่อไปแล้ว เหมือนเช่นองค์กรมาตรฐานแห่งชาติอื่น ๆ แต่ก็คล้อยตามมาตรฐานไอโซซี การรับเอามาตรฐานระดับชาติมาปรับปรุงเป็นมาตรฐานระดับสากล เกิดขึ้นภายในปีเดียวกับที่เผยแพร่มาตรฐานไอโซ

           จุดมุ่งหมายหนึ่งของกระบวนการสร้างมาตรฐานให้ภาษาซีคือเพื่อสร้างซูเปอร์เซตของภาษาเคแอนด์อาร์ซี ผสมผสานคุณลักษณะต่าง ๆ ที่ยังไม่เป็นทางการซึ่งแนะนำต่อกันมา คณะกรรมการมาตรฐานได้รวมคุณลักษณะหลายประการเพิ่มเข้ามาอาทิ ฟังก์ชันโพรโทไทป์ (ยืมมาจากภาษาซีพลัสพลัส), ตัวชี้ void, รองรับการจัดเรียงท้องถิ่น (locale) และชุดอักขระสากล, และการปรับปรุงตัวประมวลก่อนให้ดีขึ้น วากยสัมพันธ์สำหรับการประกาศพารามิเตอร์ถูกเพิ่มเข้ามาให้เหมือนกับรูปแบบที่ใช้ในภาษาซีพลัสพลัส แม้ว่าการเขียนแบบเคแอนด์อาร์ก็ยังสามารถใช้ได้เพื่อความเข้ากันได้กับรหัสต้นฉบับที่มีอยู่แล้ว

          ภาษาซีรุ่นนี้ยังคงรองรับในตัวแปลโปรแกรมในปัจจุบัน และรหัสภาษาซีส่วนใหญ่ที่เขียนขึ้นทุกวันนี้ก็ใช้พื้นฐานมาจากรุ่นนี้ โปรแกรมใด ๆ ที่เขียนขึ้นด้วยภาษาซีมาตรฐานโดยไร้สมมติฐานว่าขึ้นอยู่กับฮาร์ดแวร์ใด จะทำงานได้อย่างถูกต้องบนแพลตฟอร์มใดก็ตามด้วยการพัฒนาภาษาซีที่สอดคล้องกันภายในทรัพยากรที่จำกัด หากไม่ระมัดระวังเช่นนั้น โปรแกรมอาจแปลได้เฉพาะบนแพลตฟอร์มหนึ่งหรือด้วยตัวแปลตัวหนึ่งเท่านั้น อันเนื่องมาจากการใช้ไลบรารีไม่มาตรฐานเช่นไลบรารีส่วนต่อประสานกราฟิกกับผู้ใช้ก็ดี หรือความเชื่อมั่นต่อสมบัติเฉพาะของแพลตฟอร์มหรือตัวแปลหนึ่ง ๆ เช่นขนาดที่แท้จริงของชนิดข้อมูลหรือการลำดับข้อมูลไบต์ (endianness) ก็ดี

           ในกรณีที่ต้องเลือกว่ารหัสต้องถูกแปลด้วยตัวแปลภาษาซีมาตรฐานหรือภาษาเคแอนด์อาร์ซีอย่างใดอย่างหนึ่ง การใช้แมโคร __STDC__ สามารถช่วยให้แบ่งแยกรหัสส่วนมาตรฐานและส่วนเคแอนด์อาร์ออกจากกัน ซึ่งเป็นคุณลักษณะที่ได้เปรียบอีกอย่างหนึ่งที่มีเฉพาะในภาษาซีมาตรฐาน

ภาษาซี99

หลังจากกระบวนการทำให้เป็นมาตรฐานของแอนซี/ไอโซแล้ว ข้อกำหนดภาษาซียังคงนิ่งอยู่ชั่วระยะเวลาหนึ่ง ในขณะที่ภาษาซีพลัสพลัสกำลังก่อตัวด้วยความพยายามทำให้เป็นมาตรฐานของมันเอง การเพิ่มเติมกฎเกณฑ์ครั้งที่ 1 สำหรับมาตรฐานภาษาซีเผยแพร่เมื่อ พ.ศ. 2538 เพื่อแก้ไขรายละเอียดบางจุดและเพิ่มการรองรับชุดอักขระสากลให้มากขึ้น ต่อมามาตรฐานภาษาซีถูกเรียบเรียงดัดแปลงใหม่และนำไปสู่การเผยแพร่ ISO/IEC 9899:1999 ออกสู่สาธารณชนใน พ.ศ. 2542 ซึ่งมักถูกอ้างถึงว่า "ซี99" (C99) มาตรฐานนี้มีการเพิ่มเติมกฎเกณฑ์แล้วสามครั้งโดย Technical Corrigenda ปัจจุบันมาตรฐานภาษาซีสากลดูแลและควบคุมโดยกลุ่ม ISO/IEC JTC1/SC22/WG14
ภาษาซี99ได้แนะนำคุณลักษณะใหม่หลายประการอาทิ ฟังก์ชันแบบแทรก (inline function) ชนิดข้อมูลใหม่หลายชนิด (เช่น long long int และ complex สำหรับจำนวนเชิงซ้อนแถวลำดับความยาวแปรได้ (variable-length array) แมโครอาร์กิวเมนต์แปรได้ (variadic macro) และหมายเหตุในหนึ่งบรรทัดที่ขึ้นต้นด้วย // เหมือนภาษาบีซีพีแอลหรือภาษาซีพลัสพลัส ซึ่งคุณลักษณะส่วนใหญ่เคยพัฒนาไว้แล้วเป็นส่วนขยายของตัวแปลภาษาซีหลายโปรแกรม
ภาษาซี99สามารถเข้ากันได้แบบย้อนหลังกับภาษาซี90เป็นส่วนใหญ่ แต่ก็จำกัดมากขึ้นในบางแง่มุม โดยเฉพาะการประกาศโดยไม่ระบุชนิด จะไม่ถูกสมมติว่าเป็น int อีกต่อไป แมโครมาตรฐาน __STDC_VERSION__ ถูกนิยามขึ้นด้วยค่า 199901L เพื่อแสดงว่ารหัสนั้นรองรับภาษาซี99 ขณะนี้ จีซีซี ซันสตูดิโอ และตัวแปลโปรแกรมอื่น ๆ ก็รองรับคุณลักษณะใหม่ของภาษาซี99เป็นจำนวนมากหรือทั้งหมดแล้ว

ภาษาซี1เอกซ์

ดูบทความหลักที่: ภาษาซี1เอกซ์
เมื่อ พ.ศ. 2550 มีกลุ่มทำงานหนึ่งเริ่มต้นขึ้นเพื่อปรับปรุงมาตรฐานภาษาซีอีกรุ่น ซึ่งเรียกชื่ออย่างไม่เป็นทางการว่า "ซี1เอกซ์" (C1X) คณะกรรมการนี้รับเอาแนวคิดต่าง ๆ เพื่อจำกัดการเลือกคุณลักษณะใหม่ที่ยังไม่เคยมีการทดสอบพัฒนามาก่อน
การใช้งาน
การเขียนโปรแกรมระบบเป็นการใช้งานหลักของภาษาซี ซึ่งรวมไปถึงการพัฒนาระบบปฏิบัติการและโปรแกรมประยุกต์ระบบฝังตัว เนื่องจากลักษณะเฉพาะอันเป็นที่ต้องการถูกรวมเข้าไว้ด้วยกัน อย่างเช่น ความสามารถในเคลื่อนย้ายได้กับประสิทธิภาพของรหัสต้นฉบับ ความสามารถในการเข้าถึงที่อยู่ของฮาร์ดแวร์ที่ระบุ ความสามารถเรื่อง type punning เพื่อให้เข้ากับความต้องการการเข้าถึงข้อมูลที่กำหนดไว้จากภายนอก และความต้องการทรัพยากรระบบขณะทำงานต่ำ ภาษาซีสามารถใช้เขียนโปรแกรมเว็บไซต์โดยใช้ซีจีไอเป็น "เกตเวย์" เพื่อแลกเปลี่ยนสารสนเทศระหว่างเว็บแอปพลิเคชัน เซิร์ฟเวอร์ และเบราว์เซอร์ [16] ปัจจัยบางอย่างที่ทำให้เลือกภาษาซีแทนที่จะเป็นภาษาอินเทอร์พรีตเตอร์ คือความเร็ว เสถียรภาพ และความอ่อนไหวต่อการเปลี่ยนแปลงในสภาพแวดล้อมของการดำเนินงาน เนื่องจากเป็นธรรมชาติของภาษาคอมไพเลอร์ 
ผลจากการยอมรับในระดับกว้างขวางและประสิทธิภาพของภาษาซี ทำให้ตัวแปลโปรแกรม ตัวแปลคำสั่ง ไลบรารีต่าง ๆ ของภาษาอื่น มักพัฒนาขึ้นด้วยภาษาซี ตัวอย่างเช่น ตัวแปลโปรแกรมภาษาไอเฟลหลายโปรแกรมส่งข้อมูลออกเป็นรหัสภาษาซีเป็นภาษากลาง เพื่อส่งต่อให้ตัวแปลโปรแกรมภาษาซีต่อไป การพัฒนาสายหลักของภาษาไพทอน ภาษาเพิร์ล 5 และภาษาพีเอชพี ทั้งหมดถูกเขียนขึ้นด้วยภาษาซี
ภาษาซีมีประสิทธิภาพสำหรับคอมพิวเตอร์เพื่องานคำนวณและวิทยาศาสตร์ เนื่องจากความสิ้นเปลืองต่ำ ธรรมชาติของภาษาระดับต่ำ ธรรมชาติของภาษาที่ถูกแปล และมีส่วนคณิตศาสตร์ที่ดีในไลบรารีมาตรฐาน ตัวอย่างของการใช้ภาษาซีในงานคำนวณและวิทยาศาสตร์ เช่นจีเอ็มพี ไลบรารีวิทยาศาสตร์ของกนู แมเทอแมติกา แมตแล็บ และแซส
ภาษาซีบางครั้งใช้เป็นภาษาระหว่างกลางในการทำให้เกิดผลของภาษาอื่น แนวคิดนี้อาจใช้เพื่อความสะดวกต่อการเคลื่อนย้าย โดยให้ภาษาซีเป็นภาษาระหว่างกลาง ซึ่งไม่จำเป็นต้องพัฒนาตัวสร้างรหัสแบบเจาะจงเครื่อง ตัวแปลโปรแกรมที่ใช้ภาษาซีในทางนี้เช่น บิตซี แกมบิต จีเอชซี สควีก และวาลา เป็นต้น อย่างไรก็ตามภาษาซีถูกออกแบบมาเพื่อเป็นภาษาเขียนโปรแกรม ไม่ใช่ภาษาเป้าหมายของตัวแปลโปรแกรม จึงเหมาะสมน้อยกว่าสำหรับการใช้เป็นภาษาระหว่างกลาง ด้วยเหตุผลนี้นำไปสู่การพัฒนาภาษาระหว่างกลางที่มีพื้นฐานบนภาษาซีเช่น ภาษาซีไมนัสไมนัส
ผู้ใช้ขั้นปลายใช้ภาษาซีอย่างแพร่หลายเพื่อสร้างแอปพลิเคชันของผู้ใช้เอง แต่เมื่อแอปพลิเคชันใหญ่ขึ้น การพัฒนาเช่นนั้นมักจะย้ายไปทำในภาษาอื่นที่พัฒนามาด้วยกัน เช่นภาษาซีพลัสพลัส ภาษาซีชาร์ป ภาษาวิชวลเบสิก เป็นต้น
รหัสต้นฉบับของภาษาซีมีรูปแบบอิสระ ซึ่งสามารถใช้อักขระช่องว่างเท่าใดก็ได้ในรหัส มากกว่าที่จะถูกจำกัดด้วยคอลัมน์หรือบรรทัดข้อความอย่างภาษาฟอร์แทรน 77 ข้อความหมายเหตุจะปรากฏระหว่างตัวคั่น /* และ */ (แบบดั้งเดิม) หรือตามหลัง // จนกว่าจะจบบรรทัด (ภาษาซี99 เป็นต้นไป)
รหัสต้นฉบับแต่ละไฟล์ประกอบด้วยการประกาศและการนิยามฟังก์ชันต่าง ๆ และการนิยามฟังก์ชันก็ประกอบด้วยการประกาศและข้อความสั่งต่าง ๆ ภายในอีกด้วย การประกาศอาจกำหนดชนิดข้อมูลใหม่โดยใช้คำหลักเช่น structunion และ enum หรือกำหนดค่าของชนิดข้อมูลและอาจสงวนเนื้อที่สำรองให้กับตัวแปรใหม่ โดยการเขียนชื่อของชนิดข้อมูลตามด้วยชื่อตัวแปร คำหลักอาทิ char และ int เป็นชนิดข้อมูลพื้นฐานที่มากับภาษา ส่วนต่าง ๆ ของรหัสถูกคลุมด้วยวงเล็บปีกกา { กับ } เพื่อจำกัดขอบเขตของการประกาศ และเพื่อกระทำเสมือนข้อความสั่งเดียวสำหรับโครงสร้างการควบคุม
ภาษาซีใช้ ข้อความสั่ง (statement) ในการระบุการกระทำเช่นเดียวกับภาษาเชิงคำสั่งอื่น ข้อความสั่งที่สามัญที่สุดคือ ข้อความสั่งนิพจน์ (expression statement) ซึ่งประกอบด้วยนิพจน์ที่จะถูกนำไปประเมินค่า ตามด้วยอัฒภาค ; จากผลข้างเคียงของการประเมินค่า ฟังก์ชันหลายฟังก์ชันอาจถูกเรียกใช้และตัวแปรหลายตัวอาจถูกกำหนดค่าใหม่ ภาษาซีได้เตรียมข้อความสั่งสำหรับควบคุมการไหลของโปรแกรมไว้หลายข้อความซึ่งดูได้จากคำสงวนต่าง ๆ ตัวอย่างเช่น การใช้ if-else เพื่อการทำงานแบบมีเงื่อนไข และการใช้ do-while,while และ for เพื่อการทำงานแบบวนรอบ เพื่อปรับเปลี่ยนการทำงานอันเป็นลำดับปกติ เป็นสิ่งที่รองรับสำหรับการเขียนโปรแกรมเชิงโครงสร้าง สำหรับข้อความสั่ง for นั้นมีนิพจน์ของการกำหนดค่าเริ่มต้น การทดสอบเงื่อนไข และการกำหนดค่ารอบใหม่ทั้งสามอย่างในตัวเอง ซึ่งสามารถละเว้นนิพจน์ใดก็ได้ ข้อความสั่ง break และ continue สามารถใช้ภายในการทำงานแบบวนรอบ เพื่อหยุดการวนรอบ หรือข้ามไปยังการกำหนดค่ารอบใหม่ทันทีตามลำดับ นอกจากนี้ยังมีข้อความสั่งที่ไม่เป็นเชิงโครงสร้างคือ goto ซึ่งจะทำให้การไหลของโปรแกรมข้ามไปยังป้าย (label) ที่ตั้งชื่อไว้ทันทีภายในฟังก์ชัน ข้อความสั่ง switch และ case ใช้สำหรับพิจารณาทางเลือกของการทำงานโดยพิจารณานิพจน์ที่เป็นจำนวนเต็ม
นิพจน์ต่าง ๆ สามารถใช้ตัวดำเนินการที่มีมากับภาษาได้หลากหลาย (ดูด้านล่าง) และอาจมีการเรียกใช้ฟังก์ชัน อาร์กิวเมนต์ของฟังก์ชันและตัวถูกดำเนินการของตัวดำเนินการส่วนใหญ่ที่จะถูกประเมินค่านั้นไม่มีการระบุลำดับ การประเมินค่าจึงอาจแทรกซ้อนกันก็ได้ อย่างไรก็ตามผลกระทบที่เกิดขึ้นทั้งหมด (รวมทั้งที่เก็บข้อมูลตัวแปร) จะปรากฏก่อน จุดลำดับ (sequence point) ถัดไป จุดลำดับนั้นคือจุดสิ้นสุดของข้อความสั่งของแต่ละนิพจน์ และจุดที่เข้าและออกจากการเรียกใช้ฟังก์ชัน จุดลำดับก็ยังเกิดขึ้นระหว่างการประเมินค่านิพจน์ที่มีตัวดำเนินการบางชนิด (เช่น &&||?: และตัวดำเนินการจุลภาค) สิ่งนี้ทำให้การปรับแต่งรหัสจุดหมายให้เหมาะสมทำได้ในระดับสูง ซึ่งไม่จำเป็นต้องให้โปรแกรมเมอร์ภาษาซีใส่ใจมากนักเพื่อให้ได้ผลลัพธ์ที่เชื่อถือได้ ในขณะที่จำเป็นสำหรับภาษาโปรแกรมอื่น
ถึงแม้ว่าวากยสัมพันธ์ของภาษาซีจะถูกเลียนแบบโดยภาษาอื่นหลายภาษาเพราะว่าความเคยชินอย่างกว้างขวาง แต่ก็ถูกวิพากษ์วิจารณ์บ่อยครั้ง ตัวอย่างเช่น เคอร์นิกันและริตชีได้กล่าวในบทนำของ เดอะซีโปรแกรมมิงแลงกวิจ ไว้ว่า "ภาษาซีก็มีตำหนิของมันเหมือนภาษาอื่นใด ตัวดำเนินการบางตัวมีสิทธิการทำก่อนที่ผิด วากยสัมพันธ์บางส่วนสามารถทำให้ดีกว่านี้"
ปัญหาเฉพาะบางอย่างที่ควรหมายเหตุไว้มีดังนี้
  • ไม่มีการตรวจสอบจำนวนและชนิดของอาร์กิวเมนต์ เมื่อการประกาศฟังก์ชันมีรายการพารามิเตอร์ว่าง (สิ่งนี้เพื่อความเข้ากันได้ย้อนหลังกับภาษาเคแอนด์อาร์ซี ซึ่งไม่มีโพรโทไทป์)
  • ทางเลือกที่น่าสงสัยของสิทธิการทำก่อนของตัวดำเนินการ ดังที่กล่าวถึงโดยเคอร์นิกันและริตชีข้างต้น เช่น == ที่วางอยู่ติดกับ & และ | ในนิพจน์ดังตัวอย่าง x & 1 == 0 ตัวดำเนินการ == จะทำก่อนซึ่งไม่ใช่ผลที่คาดไว้ จำเป็นต้องใส่วงเล็บเพิ่ม (x & 1) == 0 เพื่อให้ & ทำก่อนตามต้องการ
  • ตัวดำเนินการ = ซึ่งใช้แสดงภาวะเท่ากันในคณิตศาสตร์ แต่ในภาษาซีใช้เพื่อการกำหนดค่าของตัวแปร โดยใช้ตามแบบที่มีอยู่ก่อนในภาษาฟอร์แทรน ภาษาพีแอล/วัน และภาษาเบสิก ไม่เหมือนภาษาอัลกอลและภาษาต่อยอดของมัน ริตชีตั้งใจเลือกรูปแบบนี้ด้วยเหตุผลหลักว่า อาร์กิวเมนต์ของการกำหนดค่าเกิดขึ้นบ่อยกว่าการเปรียบเทียบ
  • ความคล้ายกันของตัวดำเนินการกำหนดค่าและการเปรียบเทียบภาวะเท่ากัน (= และ ==) ทำให้เกิดความผิดพลาดจากการใช้เครื่องหมายผิดได้ง่าย ในหลายกรณีเครื่องหมายถูกใช้ในบริบทของอีกอันหนึ่งโดยไม่มีความผิดพลาดขณะแปล (แม้ว่าตัวแปลโปรแกรมปกติจะสร้างข้อความเตือนขึ้นมา) ตัวอย่างเช่น นิพจน์เงื่อนไขภายใน if (a = b) จะเป็นจริงถ้าa มีค่าไม่เป็นศูนย์หลังจากการกำหนดค่า [18] อย่างไรก็ตาม ข้อบกพร่องนี้อาจมีประโยชน์สำหรับการเขียนรหัสอย่างย่อในบางกรณี
  • การขาดตัวดำเนินการเติมกลางสำหรับวัตถุซับซ้อนหลายชนิด โดยเฉพาะการดำเนินการสายอักขระ ทำให้โปรแกรมที่ขึ้นอยู่กับการดำเนินการเหล่านี้มีขนาดใหญ่กว่าที่ควรเป็น (เพราะต้องสร้างฟังก์ชันขึ้นเอง) และทำให้รหัสอ่านยากขึ้นด้วย
  • รูปแบบของการประกาศที่บางครั้งไม่เป็นไปตามสามัญสำนึก โดยเฉพาะตัวชี้ฟังก์ชัน (แนวคิดของริตชีคือการประกาศตัวระบุในบริบทที่สัมพันธ์กับการใช้งานของมัน)

ตัวดำเนินการ

ภาษาซีรองรับตัวดำเนินการหลายประเภท ซึ่งเป็นสัญลักษณ์ที่ใช้ในนิพจน์เพื่อระบุการจัดการที่จะถูกทำให้เกิดผล ระหว่างการประเมินค่าของนิพจน์นั้น ภาษาซีมีตัวดำเนินการต่อไปนี้
ภาษาซีมีไวยากรณ์รูปนัยซึ่งระบุโดยมาตรฐานภาษาซี 

การแปลงจำนวนเต็ม จำนวนจุดลอยตัว และการปัดเศษ

วากยสัมพันธ์ของการแปลงชนิดข้อมูลสามารถใช้แปลงค่าต่าง ๆ ระหว่างชนิดข้อมูลจำนวนเต็มและจำนวนจุดลอยตัว (จำนวนทศนิยม) หรือระหว่างจำนวนเต็มสองจำนวน หรือระหว่างจำนวนจุดลอยตัวสองจำนวนที่มีขนาดแตกต่างกัน ตัวอย่างเช่น (long int)sqrt(1000.0)(double)(256*256) หรือ (float)sqrt(1000.0) เป็นต้น การแปลงชนิดข้อมูลเป็นภาวะปริยายในหลายบริบทอาทิ เมื่อกำหนดค่าให้กับตัวแปรหรือพารามิเตอร์ของฟังก์ชัน หรือเมื่อใช้จำนวนจุดลอยตัวเป็นดัชนีของเวกเตอร์ หรือในการดำเนินการทางเลขคณิตที่มีตัวถูกดำเนินการเป็นข้อมูลคนละชนิดกัน
การแปลงค่าระหว่างจำนวนเต็มและจำนวนจุดลอยตัวโดยทั่วไป จะเกิดการเปลี่ยนแปลงการเข้ารหัสระดับบิตไปยังขอบเขตที่เป็นไปได้เพื่อสงวนค่าจำนวนของตัวถูกดำเนินการนั้น ไม่เหมือนกับการแปลงชนิดข้อมูลกรณีอื่น (ซึ่งการเข้ารหัสระดับบิตของตัวถูกดำเนินการจะถูกตีความใหม่ตามชนิดเป้าหมายเพียงเท่านั้น) โดยเฉพาะอย่างยิ่ง การแปลงชนิดข้อมูลจากจำนวนเต็มไปเป็นจำนวนจุดลอยตัวจะคงไว้ซึ่งค่าจำนวนได้อย่างถูกต้อง เว้นแต่ถ้าจำนวนบิตในชนิดเป้าหมายมีไม่เพียงพอ กรณีดังกล่าวจะทำให้บิตที่มีนัยสำคัญน้อยที่สุดสูญหายไป
ส่วนการแปลงชนิดข้อมูลจากจำนวนจุดลอยตัวไปเป็นจำนวนเต็มจะเกิดการตัดค่าหลังจุดทศนิยมอย่างหลีกเลี่ยงไม่ได้ (ค่าถูกปัดเศษเข้าหาศูนย์) สำหรับการปัดเศษชนิดอื่น ภาษซี99ได้ระบุไว้แล้วในฟังก์ชันดังนี้ (ใน <math.h>)
  • round(): ปัดเศษไปยังจำนวนเต็มที่ใกล้สุด
  • rint()nearbyint(): ปัดเศษตามทิศทางของจำนวนจุดลอยตัวปัจจุบัน
  • ceil(): ค่าจำนวนเต็มน้อยสุดที่ไม่น้อยกว่าอาร์กิวเมนต์ (ปัดขึ้น) ดูเพิ่มที่ฟังก์ชันเพดาน
  • floor(): ค่าจำนวนเต็มมากสุดที่ไม่มากกว่าอาร์กิวเมนต์ (ปัดลง) ดูเพิ่มที่ฟังก์ชันพื้น
  • trunc(): ปัดเศษเข้าหาศูนย์ (เหมือนกับการแปลงชนิดข้อมูลเป็นจำนวนเต็ม)
ฟังก์ชันทั้งหมดนี้รับอาร์กิวเมนต์ double และคืนค่าเป็น double ซึ่งต่อจากนี้ก็อาจแปลงชนิดข้อมูลเป็นจำนวนเต็มอีกทีหากจำเป็น
การแปลงชนิดข้อมูลจาก float ไปเป็น double จะคงไว้ซึ่งค่าจำนวนได้อย่างถูกต้อง ในขณะที่การแปลงกลับ ค่าจะถูกปัดเศษซึ่งมักเป็นการปัดเศษเข้าหาศูนย์ เพื่อให้พอดีกับจำนวนบิตที่น้อยลง (เนื่องจาก float ก็มีช่วงเลขชี้กำลังที่น้อยกว่าด้วย การแปลงชนิดข้อมูลอาจให้ผลเป็นค่าอนันต์แทน) ตัวแปลโปรแกรมบางโปรแกรมจะแปลงค่าของ float ไปเป็นdouble โดยเบื้องหลังในบางบริบทเช่น พารามิเตอร์ของฟังก์ชันที่ประกาศเป็น float ตามความเป็นจริงอาจส่งค่าเป็น double ก็ได้
เครื่องที่ทำตามมาตรฐานจำนวนจุดลอยตัวของ IEEE เหตุการณ์การปัดเศษบางเหตุการณ์มีผลมาจากสถานะการปัดเศษปัจจุบัน (ได้แก่การปัดเศษเลขคู่ การปัดเศษขึ้น การปัดเศษลง และการปัดเศษเข้าหาศูนย์) ซึ่งอาจเรียกดูหรือตั้งค่าสถานะโดยใช้ฟังก์ชัน fegetround()/fesetround() ที่นิยามไว้ใน <fenv.h>

ไม่มีความคิดเห็น:

แสดงความคิดเห็น