ภาษซี(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
ไม่มีความคิดเห็น:
แสดงความคิดเห็น