Mở đầu Lịch sử của C Phát triển bởi Ken Thompson và Dennis Ritchie của AT&T Bell Labs vào năm 1972 Năm 1983, ANSI bắt đầu quá trình chuẩn hóa Năm 1989, ISO tiếp tục quá trình chuẩn hóa Năm 1990, quá trình chuẩn hóa kết thúc, kết quả là C90 (Standard C) Năm 1999, chuẩn được bổ sung, kết quả là C99 Lịch sử của C Ken Thompson C là sản phẩm của hệ điều hành UNIX. Năm 1970, UNIX được viết bằng Dennis Ritchie & hợp ngữ, khó dò lỗi và phát triển. Ken Thompson thiết kế một ngôn ngữ cấp Brian Kernighan cao nhằm phát triển UNIX trong tương lai, đó là ngôn ngữ B, dựa trên BCPL – một ngôn ngữ dùng viết hệ điều hành và trình biên dịch (Martin Richards, 1967). Năm 1972, Dennis Ritchie tham gia phát triển UNIX bằng ngôn ngữ B trên DEC PDP-11.
Do B không còn phù hợp, Ritchie phát triển một phiên bản mở rộng của B, gọi là NB (New B). Sau đó, Ritchie đặt tên cho ngôn ngữ mới là C. Năm 1973, UNIX được viết lại hoàn toàn bằng C. Năm 1978, Brian Kernighan và Dennis Ritchie xuất bản sách “The C Programming Language”, cuốn sách này được xem như một chuẩn thực tế của ngôn ngữ C, gọi là K&R C.
Chuẩn hóa Cộng đồng lập trình viên dùng C nhanh chóng phát triển, nhưng chuẩn thực tế K&R C còn nhiều điểm mơ hồ, vì vậy cần chuẩn hóa C. ANSI ANSI (American National Standards Institute) bắt đầu quá trình chuẩn hóa C từ năm 1983, kéo dài đến năm 1989. Kết quả là chuẩn ANSI X3. ISO Năm 1989, chuẩn trên được ISO (International Standards Organization) chấp thuận như chuẩn quốc tế ISO/IEC 9899:1990, mô tả C90, còn gọi là ANSI C.
C99 C trải qua vài thay đổi và mở rộng vào năm 1999, mô tả trong Amendment1. Phát hành chuẩn mới ISO/EIC 9899:1999; mô tả C99. Tuy nhiên C99 chưa được áp dụng rộng rãi. © Dương Thiên Tứ www.com Đặc điểm của C C là ngôn ngữ cấp thấp C là ngôn ngữ lập trình hệ thống C gọn nhẹ và khả chuyển Chương trình C có thể khó hiểu và khó tùy biến Đặc điểm của C Ngôn ngữ cấp Khác với các ngôn ngữ lập trình cấp cao (high-level), C cung cấp các tác vụ thấp gần với các chỉ thị của máy, các khái niệm truy xuất cấp độ máy, … Vì vậy các chương trình C thường có tốc độ thực thi nhanh, ít dòng lệnh, ít hao tốn vùng nhớ.
C được xem là ngôn ngữ lập trình cấp thấp (low-level language). Ngôn ngữ lập C là ngôn ngữ được lựa chọn hàng đầu để phát triển các hệ điều hành: trình hệ thống UNIX, Linux, Windows, … C được tích hợp như công cụ trên UNIX và Linux. Gọn nhẹ và khả C có ít đặc tả hơn các ngôn ngữ khác, thay vào đó C cung cấp một thư viện chuyển lớn các hàm chuẩn: xuất nhập, xử lý chuỗi, cấp phát vùng nhớ, … và các tác vụ tiện ích khác. Trình biên dịch C cũng nhỏ và dễ viết.
Sau khi chuẩn hóa, C cung cấp tính khả chuyển (portability), cho phép chương trình biên dịch được trên nhiều hệ nền. “Write Only” C mang tiếng là ngôn ngữ “Write Only”, nghĩa là dễ dàng viết code nhưng khó đọc được code. Tính linh động và gọn nhẹ của C có một tác động không mong muốn, lập trình viên C viết các chương trình hiệu quả, nhưng khó đọc nên khó tùy biến. 1 © Dương Thiên Tứ www.com Một chương trình C Báo cho trình biên dịch biết có sự tham gia của thư viện các hàm nhập xuất chuẩn (standard input and output functions) Hàm main #include <stdio.h> /* chú thích */ int main(void) { “Khởi đầu” printf("Hello\n"); printf("Welcome to C!"); “Kết thúc” return 0; } Hello Welcome to C! Cờ báo cho Hệ điều hành biết chương trình thành công Một chương trình C #include Chỉ thị biên dịch (directives) #include hướng dẫn cho bộ tiền xử lý của C (C Preprocessor) tìm khai báo hàm trong tập tin “stdio.
“stdio” viết tắt của “standard input and output” (nhập xuất chuẩn) và “.h” nghĩa là một tập tin tiêu đề (header). Chú thích Các chú thích được đặt trong cặp dấu /* và */ theo thứ tự đó và có thể trải dài trên nhiều dòng. C99 cho phép dùng // như C++, Java, … main Hàm main rất quan trọng. Nó định nghĩa điểm chương trình bắt đầu thực hiện.
Nếu bạn không viết hàm main chương trình sẽ không biên dịch. Cặp ngoặc nhọn C dùng dấu ngoặc nhọn “{” với nghĩa “khởi đầu” và dấu “}” với nghĩa “kết {} thúc”. Cặp ngoặc giúp phân chương trình thành các khối, nên dễ nhập lệnh và dễ đọc. Cặp {} trong chương trình trên bao khối hàm main.
printf Gọi hàm (function call) printf là một cách chuẩn để kết xuất dữ liệu từ chương trình. Hàm này được định nghĩa trong thư viện chuẩn stdio. Hai ký tự liên tiếp “\” (ký tự escape) và “n” (newline) là cách C xử lý tạo dòng mới. Thay vì in “\n”, con trỏ sẽ được chuyển đến đầu dòng kế tiếp.
return return trả về một trị cho Hệ điều hành. Hệ điều hành xử lý thông tin từ chương trình trả về như thế nào? MS-DOS lưu trữ nó trong biến ERRORLEVEL, được dùng trong các tập tin lô (batch). Các shell Bourne và Korn của UNIX lưu trữ nó trong một biến tạm $?, được dùng trong các shell script. 0 nghĩa là thành công.
chỉ định mã lỗi khác nhau. Tất cả các Hệ điều hành đều hỗ trợ các trị lên đến 255. 2 © Dương Thiên Tứ www.com Dạng thức của C Các phát biểu kết thúc với dấu ; Các cân chỉnh dòng được trình duyệt bỏ qua C phân biệt chữ hoa-chữ thường. Tên các từ khóa và hàm thư viện chuẩn đều là chữ thường.
Các chuỗi đặt trong cặp ngoặc kép “” Tạo dòng mới được xử lý với \n Các chương trình có thể báo thành công hay lỗi, đừng quên điều này Dạng thức của C Dấu ; Dấu ; rất quan trọng trong C. Nó báo cho trình biên dịch biết rằng một phát biểu (statements) kết thúc và một phát biểu khác bắt đầu. Nếu quên đặt nó sau từng phát biểu, bạn sẽ nhận được lỗi biên dịch. Dạng thức tự do C là ngôn ngữ dạng thức tự do (free format).
Nghĩa là bạn có thể trình bày, cân chỉnh (indentation) hoàn toàn theo ý muốn, nhưng nên theo một nguyên tắc để chương trình dễ đọc. Có thể viết một phát biểu trên nhiều dòng. Có thể phân các phần trong khối bằng dòng trắng cho dễ đọc. Các dấu cách (space) và các dấu tab trong chương trình sẽ được trình biên dịch bỏ qua.
Phân biệt chữ C là ngôn ngữ phân biệt chữ hoa với chữ thường (case sensitive). Chỉ có từ hoa chữ thường khóa int được biên dịch; các từ “Int”, “INT” hoặc các biến thể khác đều không là từ khóa. Tất cả từ khóa của C đều là chữ thường. Tất cả khoảng hàng trăm hàm trong thư viện chuẩn của C đều là chữ thường.
Từ khóa của C: auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while C99: inline restrict _Bool _Complex _Imaginary Hành vi Chúng ta đã nói rằng hàm main sẽ trả về một số nguyên cho Hệ điều hành, ngẫu nhiên nếu bạn quên điều này (chỉ có return hoặc thiếu cả return) bạn sẽ nhận được một cảnh báo lúc biên dịch. Nếu bỏ qua, chương trình sẽ có hành vi ngẫu nhiên tùy theo số nguyên ngẫu nhiên nó trả cho Hệ điều hành. 3 © Dương Thiên Tứ www.com Một ví dụ khác #include <stdio.h> Tạo hai biến nguyên a và b int main(void) { int a, b; Đọc hai số nguyên vào printf("Nhap hai so: "); “a” và “b” scanf("%i %i", &a, &b); printf("%i - %i = %i\n", a, b, a - b); Viết “a”, “b” và return 0; “a-b” theo dạng } Nhap hai so: 21 17 thức chỉ định 21 - 17 = 4 Một ví dụ khác int Từ khóa int, được dùng để khai báo (declarations) các biến kiểu nguyên (interger), Ở đây có hai biến được khai báo: “a” và “b”. scanf Hàm scanf ngược với printf.
Trong khi printf kết xuất ra màn hình, scanf lại đọc vào từ bàn phím. Chuỗi định dạng “%i” báo cho scanf đọc một số nguyên từ bàn phím. Do đó “%i %i” nghĩa là hai số nguyên sẽ được đọc, trị đầu tiên đặt vào biến “a” và trị thứ hai đặt vào biến “b”. Dấu cách giữa hai “%i” trong “%i %i” rất quan trọng: nó báo cho scanf biết rằng phải đợi một dấu cách trước khi nhận trị thứ hai.
Nếu thay bằng “%i,%i”, scanf sẽ đợi một dấu , trước khi nhận trị thứ hai. printf Ví dụ cho thấy printf và scanf là các hàm xuất nhập có định dạng. Với chuỗi định dạng “%i”, hàm scanf sẽ nhập số nguyên từ bàn phím và hàm printf sẽ xuất số nguyên ra màn hình. Chú ý trong chuỗi định dạng của printf có ba “%i”, để nhận ba trị từ hai biến (a, b) và một biểu thức (a-b).
Định dạng “%i” và “%d” giống nhau khi dùng printf. Tuy nhiên, với scanf, “%i” có thể nhận số ở hệ octal hoặc hexadecimal, trong khi “%d” chỉ nhận số thập phân. Các biểu thức Chú ý rằng C hiểu phải tính toán biểu thức “a-b” và in kết quả ra như một trị nguyên. Bạn có thể tạo một biến “c” khác, gán cho nó trị của “a-b” và in trị của “c”, nhưng không cần thiết.
4 © Dương Thiên Tứ www.com Các biến (variables) Các biến phải khai báo trước khi dùng ngay sau dấu “{” Các ký tự hợp lệ là các chữ cái, các số, “_” Ký tự đầu tiên không thể là một số C chỉ hiểu 31 ký tự đầu đối với các biến cục bộ, nếu dùng nhiều hơn sẽ bị bỏ qua Vài trình biên dịch chỉ hiểu 6 ký tự đầu đối với các biến toàn cục và các tên hàm Phân biệt chữ hoa và chữ thường Các biến Khai báo biến Trong C, tất cả các biến phải được khai báo trước khi dùng. Nghĩa là bạn phải đặt cho biến một tên (gọi là định danh – identifier), gán cho biến một kiểu, và cũng có thể khởi tạo biến với một trị) trước khi dùng. Trong C, khai báo các biến phải nằm trước tất cả các phát biểu trong khối. C99 không bắt buộc điều này.
Các tên hợp lệ Không được dùng các từ khóa dành riêng cho C làm tên biến. Chỉ có các chữ cái, các số và dấu “_” được dùng hợp lệ trong các tên biến. Ký tự đầu của biến có thể là chữ cái hay dấu “_” (theo chuẩn, nên tránh dùng ký tự “_” làm ký tự đầu).