วันจันทร์ที่ 22 ตุลาคม พ.ศ. 2555

ภาษซี


ภาษซี(C)


ภาษาซี (C) เป็นภาษาโปรแกรมบนคอมพิวเตอร์ที่มีวัตถุประสงค์ทั่วไป พัฒนาขึ้นเมื่อ พ.ศ. 2515 (ค.ศ. 1972) โดย เดนนิส ริตชี ที่เบลล์เทเลโฟนแลบอลาทอรีส์ (Bell Telephone Laboratories) เกิดขึ้นเพื่อสร้างระบบปฏิบัติการยูนิกซ์ในขณะนั้น

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

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

ประวัติ
การพัฒนาช่วงแรก

การเริ่มต้นพัฒนาภาษาซีเกิดขึ้นที่เบลล์แล็บส์ของเอทีแอนด์ทีระหว่าง พ.ศ. 2512–2516 [2] แต่ตามข้อมูลของริตชี ช่วงเวลาที่เกิดความสร้างสรรค์มากที่สุดคือ พ.ศ. 2515 ภาษานี้ถูกตั้งชื่อว่า "ซี" เพราะคุณลักษณะต่าง ๆ ต่อยอดมาจากภาษาก่อนหน้าคือ "บี" ซึ่งจากข้อมูลของเคน ทอมป์สัน (Ken Thompson) กล่าวว่าภาษาบีเป็นรุ่นที่แยกตัวออกจากภาษาบีซีพีแอลอีกทอดหนึ่ง

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

รุ่นดั้งเดิมของระบบยูนิกซ์บนพีดีพี-11ถูกพัฒนาขึ้นด้วยภาษาแอสเซมบลี เมื่อประมาณ พ.ศ. 2516 ภาษาซีเพิ่มชนิดข้อมูล struct ทำให้ภาษาซีเพียงพออย่างมีประสิทธิภาพ ซึ่งเคอร์เนลยูนิกซ์ส่วนใหญ่ถูกเขียนด้วยภาษาซี นี้ก็เป็นเคอร์เนลหนึ่งของระบบปฏิบัติการที่พัฒนาด้วยภาษาอื่นนอกเหนือจากภาษาแอสเซมบลี (ระบบอื่นเช่นมัลติกส์เขียนด้วยภาษาพีแอล/วัน เอ็มซีพีสำหรับเบอร์โรส์ บี5000เขียนด้วยภาษาอัลกอล ในปี พ.ศ. 2504)
ภาษาเคแอนด์อาร์ซี

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

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

ไลบรารีไอ/โอมาตรฐาน

ชนิดข้อมูล 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)

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

วากยสัมพันธ์

ดูบทความหลักที่ วากยสัมพันธ์ในภาษาซี

รหัสต้นฉบับของภาษาซีมีรูปแบบอิสระ ซึ่งสามารถใช้อักขระช่องว่างเท่าใดก็ได้ในรหัส มากกว่าที่จะถูกจำกัดด้วยคอลัมน์หรือบรรทัดข้อความอย่างภาษาฟอร์แทรน 77 ข้อความหมายเหตุจะปรากฏระหว่างตัวคั่น /* และ */ (แบบดั้งเดิม) หรือตามหลัง // จนกว่าจะจบบรรทัด (ภาษาซี99 เป็นต้นไป)

รหัสต้นฉบับแต่ละไฟล์ประกอบด้วยการประกาศและการนิยามฟังก์ชันต่าง ๆ และการนิยามฟังก์ชันก็ประกอบด้วยการประกาศและข้อความสั่งต่าง ๆ ภายในอีกด้วย การประกาศอาจกำหนดชนิดข้อมูลใหม่โดยใช้คำหลักเช่น struct, union และ 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 มีค่าไม่เป็นศูนย์หลังจากการกำหนดค่า อย่างไรก็ตาม ข้อบกพร่องนี้อาจมีประโยชน์สำหรับการเขียนรหัสอย่างย่อในบางกรณี

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

รูปแบบของการประกาศที่บางครั้งไม่เป็นไปตามสามัญสำนึก โดยเฉพาะตัวชี้ฟังก์ชัน (แนวคิดของริตชีคือการประกาศตัวระบุในบริบทที่สัมพันธ์กับการใช้งานของมัน)
ตัวดำเนินการ

ตัวดำเนินการในภาษาซีและภาษาซีพลัสพลัส

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

พีชคณิต (+, -, *, /, %)

การกำหนดค่า (=)

การกำหนดค่าแต่งเติม (+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=)

 ตรรกะระดับบิต (~, &, |, ^)

 การเลื่อนระดับบิต (<<, >>)

 ตรรกะแบบบูล (!, &&, ||)

 การประเมินค่าเชิงเงื่อนไข (?:)

 การทดสอบภาวะเท่ากัน (==, !=)

การรวมอาร์กิวเมนต์ฟังก์ชัน (( ))

การเพิ่มค่าและการลดค่า (++, --)

การเลือกสมาชิกในวัตถุ (., ->)

ขนาดของวัตถุ (sizeof)

ความสัมพันธ์เชิงอันดับ (<, <=, >, >=)

การอ้างอิงและการถูกอ้างอิง (&, *, [ ])

การลำดับ (,)

การจัดกลุ่มนิพจน์ย่อย (( ))

การแปลงชนิดข้อมูล (( ))

ภาษาซีมีไวยากรณ์รูปนัยซึ่งระบุโดยมาตรฐานภาษาซี
การแปลงจำนวนเต็ม จำนวนจุดลอยตัว และการปัดเศษ

วากยสัมพันธ์ของการแปลงชนิดข้อมูลสามารถใช้แปลงค่าต่าง ๆ ระหว่างชนิดข้อมูลจำนวนเต็มและจำนวนจุดลอยตัว (จำนวนทศนิยม) หรือระหว่างจำนวนเต็มสองจำนวน หรือระหว่างจำนวนจุดลอยตัวสองจำนวนที่มีขนาดแตกต่างกัน ตัวอย่างเช่น (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>

ตัวอย่างโปรแกรม "Hello World"

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

รหัสโปรแกรมรุ่นดั้งเดิมเป็นดังนี้ main()
{
printf("hello, world\n");
}


และหลังจากการปรับเปลี่ยนรหัสให้เข้ากับมาตรฐาน รหัสจึงเป็นดังนี้ [14] #include <stdio.h>

int main(void)
{
printf("hello, world\n");
return 0;
}


บรรทัดแรกของโปรแกรมเป็นคำสั่งชี้แนะตัวประมวลผลก่อน (preprocessing directive) แสดงไว้โดย #include ทำให้ตัวประมวลผลก่อน (อันเป็นเครื่องมืออย่างแรกที่พิจารณารหัสต้นฉบับขณะแปล) นำเนื้อหาข้อความทั้งหมดของไฟล์ส่วนหัวมาตรฐาน stdio.h เข้ามาแทนที่บรรทัดนั้น ซึ่งไฟล์ดังกล่าวมีการประกาศฟังก์ชันสำหรับอุปกรณ์นำเข้าและส่งออกมาตรฐานอาทิ printf วงเล็บแหลมที่คลุมชื่อไฟล์ stdio.h (ซึ่งความจริงคือเครื่องหมายน้อยกว่า-มากกว่า) เป็นการแสดงว่า stdio.h ถูกกำหนดที่ตั้งโดยใช้กลยุทธ์การค้นหาที่ให้ความสำคัญต่อไฟล์ส่วนหัวมาตรฐาน มากกว่าไฟล์ส่วนหัวอื่นที่มีชื่อเดียวกัน อัญประกาศคู่อาจใช้ได้ในกรณีที่ต้องการนำไฟล์ส่วนหัวที่อยู่ใกล้เคียงหรือเจาะจงโครงการเข้ามารวม

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

วงเล็บปีกกาเปิดหมายถึงจุดเริ่มต้นของการนิยามฟังก์ชัน main

บรรทัดถัดมาเป็นการ เรียกใช้ ฟังก์ชันที่ชื่อว่า printf ซึ่งประกาศไว้ใน stdio.h และจัดเตรียมขึ้นจากไลบรารีของระบบ ในการเรียกใช้ครั้งนี้ ฟังก์ชันprintf จะถูก ผ่านค่า ด้วยอาร์กิวเมนต์หนึ่งตัวคือตำแหน่งหน่วยความจำของอักขระตัวแรกในสายอักขระ "hello, world\n" สายอักขระดังกล่าวคือแถวลำดับที่ไม่มีชื่ออันประกอบด้วยชนิดข้อมูล char จะถูกสร้างขึ้นโดยอัตโนมัติโดยตัวแปลโปรแกรม และแถวลำดับจะมีอักขระค่าศูนย์ (null) เป็นสิ่งที่บ่งบอกจุดสิ้นสุดของสายอักขระ (printf จำเป็นต้องทราบสิ่งนี้) \n ที่ปรากฏในสายอักขระคือ ลำดับการหลีก (escape sequence) ภาษาซีจะตีความว่าเป็นอักขระ newline (ขึ้นบรรทัดใหม่) ซึ่งจะทำให้อุปกรณ์ส่งออกทราบว่าถึงจุดสิ้นสุดของบรรทัดปัจจุบัน ค่าส่งคืนจากฟังก์ชัน printf คือชนิด int แต่มันถูกละทิ้งไปอย่างเงียบ ๆ เนื่องจากไม่มีการใช้ (โปรแกรมที่ระมัดระวังมากกว่าอาจทดสอบค่าส่งคืน เพื่อพิจารณาว่าผลจากการทำงานของฟังก์ชัน printfสำเร็จหรือไม่) อัฒภาค ; เป็นจุดสิ้นสุดข้อความสั่ง

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