การพัฒนาช่วงแรก
การเริ่มต้นพัฒนาภาษาซีเกิดขึ้นที่เบลล์แล็บส์ของ
เอทีแอนด์ทีระหว่าง พ.ศ. 2512–2516 แต่ตามข้อมูลของริตชี ช่วงเวลาที่เกิดความสร้างสรรค์มากที่สุดคือ พ.ศ. 2515 ภาษานี้ถูกตั้งชื่อว่า "ซี" เพราะคุณลักษณะต่าง ๆ ต่อยอดมาจากภาษาก่อนหน้าคือ "บี" ซึ่งจากข้อมูลของ
เคน ทอมป์สัน (Ken Thompson) กล่าวว่าภาษาบีเป็นรุ่นที่แยกตัวออกจาก
ภาษาบีซีพีแอลอีกทอดหนึ่ง
จุดเริ่มต้นของภาษาซีผูกอยู่กับการพัฒนาระบบปฏิบัติการยูนิกซ์อย่างใกล้ชิด ซึ่งเดิมพัฒนาด้วยภาษาแอสเซมบลีบนหน่วยประมวลผล
พีดีพี-7โดยริตชีและทอมป์สัน โดยผสมผสานความคิดหลากหลายจากเพื่อนร่วมงาน ในตอนท้ายพวกเขาตัดสินใจที่จะย้ายระบบปฏิบัติการนั้นลงในพีดีพี-11 แต่ภาษาบีขาดความสามารถบางอย่างที่จะใช้คุณลักษณะอันได้เปรียบของพีดีพี-11 เช่นความสามารถในการระบุตำแหน่งที่อยู่เป็น
ไบต์ จึงทำให้เกิดการพัฒนาภาษาซีรุ่นแรกขึ้นมา
รุ่นดั้งเดิมของระบบยูนิกซ์บนพีดีพี-11ถูกพัฒนาขึ้นด้วยภาษาแอสเซมบลี เมื่อประมาณ พ.ศ. 2516 ภาษาซีเพิ่มชนิดข้อมูล
struct
ทำให้ภาษาซีเพียงพออย่างมีประสิทธิภาพ ซึ่ง
เคอร์เนลยูนิกซ์ส่วนใหญ่ถูกเขียนด้วยภาษาซี นี้ก็เป็นเคอร์เนลหนึ่งของระบบปฏิบัติการที่พัฒนาด้วยภาษาอื่นนอกเหนือจากภาษาแอสเซมบลี (ระบบอื่นเช่น
มัลติกส์เขียนด้วย
ภาษาพีแอล/วัน เอ็มซีพีสำหรับ
เบอร์โรส์ บี5000เขียนด้วยภาษาอัลกอล ในปี พ.ศ. 2504)
ภาษาเคแอนด์อาร์ซี
เมื่อ พ.ศ. 2521
ไบรอัน เคอร์นิกัน (Brian Kernighan) และเดนนิส ริตชี ได้ตีพิมพ์หนังสือเล่มแรกชื่อ
เดอะซีโปรแกรมมิงแลงกวิจ (The C Programming Language) ซึ่งเป็นที่รู้จักในกลุ่มโปรแกรมเมอร์ภาษาซีว่า "เคแอนด์อาร์" (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)
ส่วนขยายที่เพิ่มขึ้นอย่างมากและการขาดข้อตกลงในเรื่อง
ไลบรารีมาตรฐาน อีกทั้งความนิยมในภาษาและข้อเท็จจริงที่ว่าไม่เพียงแต่ตัวแปลโปรแกรมยูนิกซ์เท่านั้นที่พัฒนาขึ้นตามข้อกำหนดของเคแอนด์อาร์ ทั้งหมดนำไปสู่ความสำคัญของการทำให้เป็นมาตรฐาน
ภาษาแอนซีซีและภาษาไอโซซี
เมื่อ พ.ศ. 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เอกซ์
เมื่อ พ.ศ. 2550 มีกลุ่มทำงานหนึ่งเริ่มต้นขึ้นเพื่อปรับปรุงมาตรฐานภาษาซีอีกรุ่น ซึ่งเรียกชื่ออย่างไม่เป็นทางการว่า "ซี1เอกซ์" (C1X) คณะกรรมการนี้รับเอาแนวคิดต่าง ๆ เพื่อจำกัดการเลือกคุณลักษณะใหม่ที่ยังไม่เคยมีการทดสอบพัฒนามาก่อน