Tài liệu Bài 15: Hàm - Lí thuyết pdf

20 317 0
Tài liệu Bài 15: Hàm - Lí thuyết pdf

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Bài 15: Hàm Mục tiêu: Kết thúc học này, bạn có thể:  Tìm hiểu cách sử dụng hàm  Tìm hiều cấu trúc hàm  Khai báo hàm nguyên mẫu hàm  Thảo luận kiểu khác biến  Tìm hiểu cách gọi hàm: • • Gọi giá trị Gọi tham chiếu  Tìm hiểu qui tắc phạm vi hàm  Tìm hiểu hàm chương trình có nhiều tập tin  Tìm hiểu lớp lưu trữ  Tìm hiểu trỏ hàm Giới thiệu Một hàm đoạn chương trình thực tác vụ định nghĩa cụ thể Chúng thực chất đoạn chương trình nhỏ giúp giải vấn đề lớn 15.1 Sử dụng hàm Nói chung, hàm sử dụng C để thực thi chuỗi lệnh liên tiếp Tuy nhiên, cách sử dụng hàm khơng giống với vịng lặp Các vịng lặp lặp lại chuỗi thị với lần lặp liên tiếp Nhưng việc gọi hàm sinh chuỗi thị thực thi vị trí chương trình Các hàm gọi nhiều lần có yêu cầu Giả sử phần mã lệnh chương trình dùng để tính tỉ lệ phần trăm cho vài số Nếu sau đó, chương trình, việc tính tốn cần phải thực số khác, thay phải viết lại thị giống trên, hàm viết để tính tỉ lệ phần trăm số Sau chương trình nhảy đến hàm đó, để thực việc tính tốn (trong hàm) trở nơi gọi Điều giải thích rõ ràng thảo luận cách hoạt động hàm Một điểm quan trọng khác hàm dễ viết dễ hiểu Các hàm đơn giản viết để thực tác vụ xác định Việc gỡ rối chương trình dễ dàng cấu trúc chương trình dễ đọc, nhờ vào đơn giản hóa hình thức Mỗi hàm kiểm tra cách độc lập với liệu đầu vào, với liệu hợp lệ khơng hợp lệ Các chương trình chứa hàm dễ bảo trì hơn, sửa đổi, yêu cầu, giới hạn hàm chương trình Một hàm khơng gọi từ vị trí bên chương trình, mà hàm cịn đặt vào thư viện sử dụng nhiều chương trình khác, tiết kiệm thời gian viết chương trình 15.2 Cấu trúc hàm Cú pháp tổng quát hàm C là: Hàm 209 type_specifier function_name (arguments) { body of the function return statement } type_specifier xác định kiểu liệu giá trị trả hàm Nếu khơng có kiểu đưa ra, hàm cho trả kết số nguyên Các đối số phân cách dấu phẩy Một cặp dấu ngoặc rỗng () phải xuất sau tên hàm hàm không chứa đối số Các tham số xuất cặp dấu ngoặc () gọi tham số hình thức đối số hình thức Phần thân hàm chứa nhiều câu lệnh Một hàm nên trả giá trị lệnh return phải có hàm 15.2.1 Các đối số hàm Trước thảo luận chi tiết đối số, xem ví dụ sau, #include main() { int i; for(i =1; i b?a:b); Tuy nhiên, giới hạn lệnh return trả giá trị 15.2.3 Kiểu hàm type-specifier sử dụng để xác định kiểu liệu trả hàm Trong ví dụ trên, typespecifier khơng viết bên cạnh hàm squarer(), squarer() trả giá trị kiểu int typespecifier không bắt buộc giá trị kiểu số nguyên trả khơng có giá trị Hàm 211 trả Tuy nhiên, tốt nên kiểu liệu trả int giá trị số nguyên trả tương tự dùng void hàm không trả giá trị 15.3 Gọi hàm Có thể gọi hàm từ chương trình cách sử dụng tên hàm, theo sau cặp dấu ngoặc () Cặp dấu ngoặc cần thiết để nói với trình biên dịch là lời gọi hàm Khi tên hàm sử dụng chương trình gọi, tên hàm phần một lệnh câu lệnh Mà ta biết câu lệnh kết thúc với dấu chấm phẩy (;) Tuy nhiên, định nghĩa hàm, không dùng dấu chấm phầy cuối phần định nghĩa Sự vắng mặt dấu chấm phẩy nói với trình biên dịch phần định nghĩa hàm không gọi hàm Một số điểm cần nhớ:  Một dấu chấm phẩy dùng cuối câu lệnh hàm gọi, khơng dùng sau định nghĩa hàm  Cặp dấu ngoặc () bắt buộc theo sau tên hàm, cho dù hàm có đối số hay không  Hàm gọi đến hàm khác gọi hàm gọi hay thủ tục gọi Và hàm gọi đến gọi hàm gọi hay thủ tục gọi  Các hàm không trả giá trị số nguyên cần phải xác định kiểu giá trị trả  Chỉ giá trị trả hàm  Một chương trình có nhiều hàm 15.4 Khai báo hàm Nếu mMột hàm nên gọikhai báo hàm main() trước định nghĩa sử dụng Điều phải thực trường hợp hàm gọi trước định nghĩa.thi hàm phải khai báo hàm main() trước sử dụng Xem ví dụ, #include main() { address(); } address() { } Hàm main() gọi hàm address() hàm address() gọi trước định nghĩa Mặc dù, khơng khai báo hàm main() điều thực số trình biên dịch C, hàm address() gọi mà khơng cần khai báo thêm Đây khai báo không tường minh hàm 212 Lập trình C 15.5 Các nguyên mẫu hàm Một nguyên mẫu hàm khai báo hàm xác định rõ kiểu liệu đối số trị trả Thông thường, hàm khai báo cách xác định kiểu giá trị trả hàm, tên hàm Tuy nhiên, chuẩn ANSI C cho phép số lượng kiểu liệu đối số hàm khai báo Một hàm abc() có hai đối số kiểu int x y, trả giá trị kiểu char, khai báo sau: char abc(); char abc(int x, nt y); Cách định nghĩa sau gọi nguyên mẫu hàm Khi nguyên mẫu sử dụng, C tìm thơng báo kiểu liệu không hợp lệ chuyển đổi đối số dùng để gọi hàm với định nghĩa kiểu tham số Một lỗi thơng báo có khác số lượng đối số sử dụng để gọi hàm số lượng tham số định nghĩa hàm Cú pháp tổng quát nguyên mẫu hàm: type function_name(type parm_namel,type parm_name2, type parm_nameN); Khi hàm khai báo khơng có thơng tin ngun mẫu, trình biên dịch cho khơng có thơng tin tham số đưa Một hàm đối số gây lỗi khai báo khơng có thơng tin ngun mẫu Để tránh điều này, hàm khơng có tham số, ngun mẫu sử dụng void cặp dấu ngoặc () Như nói trên, void sử dụng để khai báo tường minh hàm khơng có giá trị trả Ví dụ, hàm noparam() trả kiểu liệu char khơng có tham số gọi, khai báo sau char noparam(void); Khai báo hàm tham số, lời gọi có truyền tham số đến hàm khơng Khi hàm không nguyên mẫu gọi tất kiểu char đổi thành kiểu int tất kiểu float đổi thành kiểu double Tuy nhiên, hànghàm nguyên mẫu, kiểu đưa ngun mẫu giữ ngun khơng có tăng cấp kiểu xảy 15.6 Các biến Như thảo luận, biến vị trí đặt tên nhớ, sử dụng để chứa giá trị khơng thể sửa đổi chương trình hàm Có ba loại biến bản: biến cục bộ, tham số hình thức, biến toàn cục 1.Biến cục biến khai báo bên hàm 2.Tham số hình thức khai báo định nghĩa hàm tham số 3.Biến toàn cục khai báo bên hàm 15.6.1 Biến cục Biến cục cịn gọi biến động, từ khố auto sử dụng để khai báo chúng Chúng tham chiếu đến lệnh bên khối lệnh mà biến khai báo Để rõ hơn, biến Hàm 213 cục tạo lúc vào khối bị huỷ lúc khỏi khối Khối lệnh thơng thường mà biến cục khai báo hàm Xem đoạn mã lệnh sau: void blkl(void) { char ch; ch = ‘a’; } void blk2(void) { char ch; ch = ‘b’; } /* void denotes no value returned*/ Biến ch khai báo hai lần, blk1() blk2() ch blk1() khơng có liên quan đến ch blk2() ch biết đến khối lệnh mà khai báo Vì biến cục tạo huỷ khối mà chúng khai báo, nên nội dung chúng bị bên phạm vi khối Điều có nghĩa chúng khơng thể trì giá trị chúng lần gọi hàm Từ khóa auto dùng để khai báo biến cục bộ, thường khơng dùng biến khơng tồn cục xem biến cục Các biến cục sử dụng hàm thường khai báo sau dấu ngoặc mở ‘{‘ hàm trước tất câu lệnh Tuy nhiên, khai báo bên khối hàm Ví dụ, void blk1(void) { int t; t = 1; if(t > 5) { char ch; } } Trong ví dụ biến ch tạo hợp lệ bên khối mã lệnh if’ Nó khơng thể tham chiếu đến phần khác hàm blk1() Một thuận lợi khai báo biến theo cách nhớ cấp phát cho điều kiện để vào khối lệnh if thoả Điều biến cục khai báo vào khối lệnh mà biến định nghĩa Chú ý: Điều quan trọng cần nhớ tất biến cục phải khai báo điểm bắt đầu khối mà chúng định nghĩa, trước tất câu lệnh thực thi 214 Lập trình C Ví dụ sau khơng làm việc với số trình biên dịch void blk1(void) { int len; len = 1; char ch; /* This will cause an error */ ch = ‘a’; } 15.6.2 Tham số hình thức Một hàm sử dụng đối số phải khai báo biến để nhận giá trị đối số Các biến gọi tham số hình thức hàm hoạt động giống biến cục bên hàm Các biến khai báo bên cặp dấu ngoặc () theo sau tên hàm Xem ví dụ sau: blk1(char ch, int i) { if(i > 5) ch = ‘a’; else i = i +1; return; } Hàm blk1() có hai tham số: ch i Các tham số hình thức phải khai báo với kiểu chúng Như ví dụ trên, ch có kiều char i có kiểu int Các biến sử dụng bên hàm biến cục bình thường Chúng bị huỷ khỏi hàm Cần ý tham số hình thức khai báo có kiểu liệu với đối số sử dụng gọi hàm Trong trường hợp có sai, C khơng hiển thị lỗi đưa kết khơng mong muốn Điều vì, C đưa vài kết tình khác thường Người lập trình phải đảm bảo khơng có lỗi sai kiểu Cũng giống với biến cục bộ, phép gán thực hiên với tham số hình thức hàm chúng sử dụng biểu thức mà C cho phép 15.6.3 Biến toàn cục Các biến toàn cục biến thấy tồn chương trình, sử dụng mã lệnh Chúng khai báo bên ngồi hàm chương trình lưu giá trị chúng suốt thực thi chương trình Các biến khai báo bên main() khai báo nơi đâu trước lần sử dụng Tuy nhiên, tốt để khai báo biến toàn cục đầu chương trình, nghĩa trước hàm main() int ctr; /* ctr is global */ void blk1(void); void blk2(void); void main(void) { Hàm 215 ctr = 10; blk1 (); } void blk1(void) { int rtc; if (ctr > 8) { rtc = rtc + 1; blk2(); } } void blk2(void) { int ctr; ctr = 0; } Trong đoạn mã lệnh trên, ctr biến toàn cục khai báo bên ngồi hàm main() blk1(), tham chiếu đến hàm Biến ctr blk2(), biến cục liên quan với biến tồn cục ctr Nếu biến tồn cục cục có tên, tất tham chiếu đến tên bên khối chứa định nghĩa biến cục kết hợp với biến cục mà khơng phải biến tồn cục Các biến toàn cục lưu trữ vùng cố định nhớ Các biến toàn cục hữu dụng nhiều hàm chương trình sử dụng liệu Tuy nhiên, nên tránh sử dụng biến tồn cục khơng cần thiết, chúng giữ nhớ suốt thời gian thực chương trình Vì việc sử dụng biến toàn cục nơi mà biến cục có khả đáp ứng cho hàm sử dụng khơng hiệu Ví dụ sau giúp làm rõ điều này: void addgen(int i, int j) { return(i + j); } int i, j; void addspe(void) { return(i + j); } Cả hai hàm addgen() addspe() trả tổng biến i j Tuy nhiên, hàm addgen() sử dụng để trả tổng hai số bất kỳ; hàm addspe() trả tổng biến toàn cục i j 15.7 Lớp lưu trữ (Storage Class) Mỗi biến C có đặc trưng gọi lớp lưu trữ Lớp lưu trữ xác định hai khía cạnh biến: thời gian sống biến phạm vi biến Thời gian sống biến thời gian mà giá trị biến tồn Phạm viSự thấy biến xác định phần chương trình nhận biến Một biến có tầm nhìn khối, hàm, tập tin, nhóm tập tin, tồn chương trình.Một biến xuất khối, hàm, tập tin, nhóm tập tin, tồn chương trình 216 Lập trình C Theo cách nhìn trình biên dịch C, tên biến xác định vài vị trí vật lý bên máy tính, chuỗi bit biểu diễn giá trị lưu trữ biến Có hai loại vị trí máy tính mà giá trị biến lưu trữ: nhớ ghi CPU Lớp lưu trữ biến xác định vị trí biến lưu trữ nhớ hay ghi C có bốn lớp lưu trữ Đó là:     auto external static register Đó từ khoá Cú pháp tổng quát cho khai báo biến sau: storage_specifier type var_name; 15.7.1 Biến tự động Biến tự động thật biến cục mà nói Phạm vi biến tự động nhỏ hàm, khai báo bên câu lệnh ghép: phạm vi bị giới hạn câu lệnh ghép Chúng khai báo từ khóa auto, khai báo khơng cần thiết Bất kỳ biến khai báo bên hàm khối lệnh thuộc lớp auto hệ thống cung cấp vùng nhớ yêu cầu cho biến 15.7.2 Biến ngoại Trong C, chương trình lớn chia thành module nhỏ hơn, module biên dịch riêng lẻ liên kết lại với Điều thực nhằm tăng tốc độ trình biên dịch chương trình lớn Tuy nhiên, module liên kết, tập tin phải chương trình thơng báo cho biết biến toàn cục yêu cầu Một biến toàn cục khai báo lần Nếu hai biến tồn cục có tên khai báo tập tin, thông điệp lỗi ‘duplicate variable name’ (tên biến trùng) hiển thị đơn giản trình biên dịch C chọn biến khác Một lỗi tương tự xảy tất biến tồn cục u cầu chương trình chứa tập tin Mặc dù trình biên dịch không đưa thông báo lỗi biên dịch, thật biến tạo Tại thời điểm liên kết tập tin, liên kết hiển thị thông báo lỗi sau ‘duplicate label’ (nhãn trùng nhau) khơng biết sử dụng biến Lớp extern dùng trường hợp Tất biến toàn cục khai báo tập tin biến giống khai báo biến ngoạiở tất tập tin Xem đoạn mã lệnh sau: Filel int i,j; char a; main() { } abc() { i = 123; } Hàm File2 extern int i,j; extern char a; xyz() { i = j * } pqr() { j = 50; } 217 File2 có biến tồn cục giống File1, ngoại trừ điểm biến có từ khóa extern thêm vào khai báo chúng Từ khóa nói với trình biên dịch tên kiểu biến toàn cục sử dụng mà không cần phải tạo lại lưu trữ cho chúng Khi hai module liên kết, tham chiếu đến biến ngoại giải Nếu biến khơng khai báo hàm, trình biên dịch kiểm tra có so khớp với biến tồn cục khơng Nếu khớp với biến tồn cục, trình biên dịch xem biến toàn cục tham chiếu đến 15.7.3 Biến tĩnh Các biến tĩnh biến cố định bên hàm tập tin Không giống biến tồn cục, chúng khơng biết đến bên hàm tập tin chúng, chúng giữ giá trị chúng lần gọi Điều có nghĩa là, hàm kết thúc sau gọi lại, biến tĩnh định nghĩa hàm giữ giá trị chúng Sự khai báo biến tĩnh bắt đầu với từ khóa static Có thể định nghĩa biến tĩnh có tên hướng dẫn với biến ngoại Các biến cục (biến tĩnh biến động) có độ ưu tiên cao biến ngoại giá trị biến ngoại không ảnh hưởng thay đổi biến cục Các biến ngoại có tên với biến nội hàm truy xuất trực tiếp bên hàm Các giá trị khởi tạo gán cho biến khai báo biến tĩnh, giá trị phải biểu thức Trình biên dịch tự động gán giá trị đến biến tĩnh không khởi tạo Sự khởi tạo thực đầu chương trình Xem hai chương trình sau Sự khác biến cục bộ: tự động tĩnh làm rõ Ví dụ biến tự động: #include main() { incre(); incre(); incre(); } incre() { char var = 65; /* var is automatic variable*/ printf(“\nThe character stored in var is %c”, var++); } kKết thực thi chương trình là: The character stored in var is A The character stored in var is A The character stored in var is A Ví dụ biến tĩnh: #include 218 Lập trình C main() { incre(); incre(): incre(): } incre() { static char var = 65; /* var is static variable */ printf(“nThe character stored in var is %c”, var++); } kKết thực thi chương trình là: The character stored in var is A The character stored in var is B The character stored in var is C Cả hai chương trình gọi incre() ba lần Trong chương trình thứ nhất, lần incre() gọi, biến var với lớp lưu trữ auto (lớp lưu trữ mặc định) khởi tạo lại 65 (là mã ASCII tương ứng ký tự A) Vì kết thúc hàm, giá trị var (66) bị (ASCII ứng với ký tự B) Trong chương trình thứ hai, var lớp lưu trữ static Ở var khởi tạo 65 lần biên dịch chương trình Cuối lần gọi hàm đầu tiên, var có giá trị 66 (ASCII B) tương tự lần gọi var có giá trị 67 (ASCII C) Sau lần gọi hàm cuối cùng, var tăng giá trị theo thực thithi hành lệnh printf() Giá trị bị chương trình kết thúc 15.7.4 Biến ghi Các máy tính có ghi số học logic - Arithmetic Logic Unit (ALU), ghi sử dụng để tạm thời lưu trữ liệu truy xuất thường xuyên Kết tức thời phép tính tốn lưu vào ghi Các thao tác thực liệu lưu trữ ghi nhanh liệu nhớ Trong ngôn ngữ assembly (hợp ngữ), người lập trình phải truy xuất đến ghi sử dụng chúng để giúp chương trình chạy nhanh Các ngơn ngữ lập trình bậc cao thường khơng truy xuất đến ghi máy tính Trong C, việc lựa chọn vị trí lưu trữ cho giá trị tùy thuộc vào người lập trình Nếu giá trị đặc biệt dùng thường xuyên (ví dụ giá trị điều khiển vòng lặp), lớp lưu trữ khai báo register Sau trình biên dịch tìm thấy ghi cịn trống, ghi máy tính đủ lớn để chứa biến, biến đặt vào ghi Ngược lại, trình biên dịch xem biến ghi biến động khác, nghĩa lưu trữ chúng nhớ Từ khóa register dùng định nghĩa biến ghi Phạm vi khởi tạo biến ghi giống biến động, ngoại trừ vị trí lưu trữ Các biến ghi cục hàm Nghĩa là, chúng tồn hàm gọi giá trị bị thoát khỏi hàm Sự khởi tạo biến thực người lập trình Vì số lượng ghi có hạn, lập trình viên cần xác định biến chương trình sử dụng thường xuyên để khai báo chúng biến ghi Sự hữu dụng biến ghi thay đổi từ máy đến máy khác từ trình biên dịch C đến trình biên dịch khác Đơi biến ghi không hỗ trợ tất – từ khóa register chấp nhận xem giống từ khóa auto Trong trường hợp khác, biến ghi hỗ trợ lập trình viên sử dụng chúng cách hợp lý, chương trình thực thi nhanh gấp đôi Hàm 219 Các biến ghi khai báo bên dưới: register int x; register char c; Sự khai báo ghi gắn vào biến động tham số hình thức Trong trường hợp sau, khai báo giống sau: f(c,n) register int c, n; { register int i; } Xét ví dụ, chương trình hiển thị tổng lập phương số thành phần số số Ví dụ 370 số vậy, vì: 33 + 73 + 03 = 27 + 343 + = 370 Chương trình sau in số khoảng đến 999 #include main() { register int i; int no, digit, sum; printf(“\nThe numbers whose Sum of Cubes of Digits is Equal to the number itself are:\n\n”); for(i = 1; i < 999; i++) { sum = 0; no = i; while(no) { digit = no%10; no = no/10; sum = sum + digit * digit * digit; } if (sum == i) printf(“t%d\n”, i); } } Kết thực thi chương trình sau: The numbers whose Sum of Cubes of Digits is Equal to the number itself are: 153 370 220 Lập trình C 371 407 Trong chương trình trên, giá trị i , thay đổi từ đến 999 Với giá trị này, lập phương số riêng lẻ cộng kết tổng so sánh với i Nếu hai giá trị nahunhau, i hiển thị Vì i sử dụng để điều khiển lặp, (phần chương trình), khai báo lớp lưu trữ ghi Sự khai báo làm tăng hiệu chương trình 15.8 Các qui luật phạm vi hàm Qui luật phạm vi qui luật định đoạn mã lệnh truy xuất đến đoạn mã lệnh khác hayhoặc liệu hay không Trong C, hàm chương trình khối lệnh riêng lẻ Mã lệnh bên hàm cục với hàm truy xuất lệnh hàm, ngoại trừ lời gọi hàm Mã lệnh bên hàm ẩn phần lại chương trình, trừ sử dụng biến liệu tồn cục, tác động bị tác động phần khác chương trình Để rõ hơn, mã lệnh liệu định nghĩa bên hàm tương tác với mã lệnh hay liệu định nghĩa hàm khác hai hàm có phạm vi khác Trong C, tất hàm có mức phạm vi Nghĩa là, hàm định nghĩa bên hàm khác Chính lý mà C ngôn ngữ cấu trúc khối mặt kỹ thuật 15.9 Gọi hàm Một cách tổng quát, hàm giao tiếp với cách truyền tham số Các tham số truyền theo hai cách sau:  Truyền giá trị  Truyền tham chiếu 15.9.1 Truyền giá trị Mặc nhiên C, tất đối số hàm truyền giá trị Điều có nghĩa là, đối số truyền đến hàm gọi, giá trị truyền thông qua biến tạm Mọi thao tác thực biến tạm Hàm gọi thay đổi giá trị chúng Xem ví dụ sau, #include main() { int a, b, c; a = b = c = 0; printf(“\nEnter 1st integer: “); scanf(“%d”, &a); printf(“\nEnter 2nd integer: “); scanf(“%d”, &b); c = adder(a, b); printf(“\n\na & b in main() are: %d, % d”, a, b); printf(“\n\nc in main() is: %d”, c); /* c gives the addition of a and b */ } adder(int a, int b) { Hàm 221 int c; c = a + b; a *= a; b += 5; printf(“\n\na & b within adder function are: %d, %d “, a, b); printf(“\nc within adder function is : %d”,c); return(c); } Ví dụ kết thực thi nhập vào 4: a c a c & b in main() are: 2, in main() is: & b within adder function are: 4, within adder function is : Chương trình nhận hai số nguyên, hai số truyền đến hàm adder() Hàm adder() thực sau: nhận hai số nguyên đối số nó, cộng chúng lại, tính bình phương cho số nguyên thứ nhất, cộng vào số nguyên thứ hai, in kết trả tổng đối số thực Các biến sử dụng hàm main() adder() có tên Tuy nhiên, khơng có chung chúng Chúng lưu trữ vị trí nhớ khác Điều thấy rõ từ kết chương trình Các biến a b hàm adder() thay đổi từ thành Tuy nhiên, thay đổi không ảnh hưởng đến giá trị a b hàm main() Các biến lưu vị trí nhớ khác Biến c main() khác với biến c adder() Vì vậy, đối số gọi truyền giá trị giá trị biến truyền đến hàm gọi thay đổi treên giá trị không ảnh hưởng đến giá trị gốc biến truyền 15.9.2 Truyền tham chiếu Khi đối số truyền giá trị, giá trị đối số hàm gọi không bị thay đổi Tuy nhiên, có trường hợp, giá trị đối số phải thay đổi Trong trường hợp vậy, truyền tham chiếu dùng Truyền tham chiếu, hàm phép truy xuất đến vùng nhớ thực đối số thay đổi giá trị đối số hàm gọi Ví dụ, xét hàm, hàm nhận hai đối số, hoán vị giá trị chúng trả giá trị chúng Nếu chương trình giống chương trình viết để giải mục đích này, khơng thực #include main() { int x, y; x = 15; y = 20; printf(“x = %d, y = %d\n”, x, y); swap(x, y); printf(“\nAfter interchanging x = %d, y = %d\n”, x, y); } swap(int u, int v) { int temp; temp = u; u = v; v = temp; 222 Lập trình C } return; Kết thực thi chương trình sau: x = 15, y = 20 After interchanging x = 15, y = 20 Hàm swap() hoán vị giá trị u v, giá trị không truyền trở hàm main() Điều biến u v swap() khác với biến u v dùng main() Truyền tham chiếu sử dụng trường hợp để đạt kết mong muốn, thay đổi giá trị đối số thực Các trỏ dùng thực truyền tham chiếu Các trỏ truyền đến hàm đối số phép hàm gọi chương trình truy xuất biến mà phạm vi khơng vượt khỏi hàm gọi Khi trỏ truyền đến hàm, địa liệu truyền đến hàm nên hàm tự truy xuất nội dung địa Các hàm gọi nhận thay đổi nội dung địa Theo cách này, đối số hàm cho phép liệu thay đổi hàm gọi, cho phép truyền liệu hai chiều hàm gọi hàm gọi Khi đối số hàm trỏ mảng, truyền tham chiếu tạo đối nghịch với cách truyền giá trị Các đối số hình thức hàm trỏ phải có dấu * phía trước, giống khai báo biến trỏ, để xác định chúng trỏ Các đối số thực kiểu trỏ lời gọi hàm khai báo biến trỏ biến tham chiếu đến (&var) Ví dụ, định nghĩa hàm getstr(char *ptr_str, int *ptr_int) đối số ptr_str trỏ đến kiểu char ptr_int trỏ đến kiểu int Hàm gọi câu lệnh, getstr(pstr, &var) pstr khai báo trỏ địa biến var truyền Gán giá trị thông qua, *ptr_int = var; Hàm gán giá trị đến biến var hàm gọi, cho phép truyền theo hai chiều đến từ hàm char *pstr; Quan sát ví dụ sau hàm swap() Bài toán giải trỏ truyền thay dùng biến Mã lệnh tương tự sau: #include void main() { int x, y, *px, *py; /* Storing address of x in px */ px = &x; /* Storing address of y in py */ Hàm 223 py = &y; x = 15; y = 20; printf(“x = %d, y = %d \n”, x, y); swap (px, py); } /* Passing addresses of x and y */ printf(“\n After interchanging x = %d, y = %d\n”, x, y); swap(int *u, int *v) /* Accept the values of px and py into u and v */ { int temp; temp = *u; *u = *v; *v = temp; return; } Kết thực thi chương trình sau: x = 15, y = 20 After interchanging x = 20, y = 15 Hai biến kiểu trỏ px py khai báo, địa biến x y gán đến chúng Sau biến trỏ truyền đến hàm swap(), hàm hoán vị giá trị lưu x y thông qua trỏ 15.10 Sự lồng lời gọi hàm Lời gọi hàm từ hàm khác gọi lồng lời gọi hàm Một chương trình kiểm tra chuỗi có phải chuỗi đọc xi - đọc ngược hay khơng, ví dụ cho lời gọi hàm lồng Từ đọc xuôi - ngược giống chuỗi ký tự đối xứng Xem đoạn mã lệnh theo sau đây: main() { palindrome(); } palindrome() { getstr(); reverse(); cmp(); } 224 Lập trình C Trong chương trình trên, hàm main() gọi hàm palindrome() Hàm palindrome() gọi đến ba hàm khác getstr(), reverse() cmp() Hàm getstr() để nhận chuỗi ký tự từ người dùng, hàm reverse() đảo ngược chuỗi hàm cmp() so sánh chuỗi nhập vào chuỗi đảo Vì main() gọi palindrome(), hàm palindrome() gọi hàm getstr(), reverse() cmp(), lời gọi hàm gọi lồng bên palindrome() Sự lồng lời gọi hàm phép, định nghĩa hàm bên hàm khác không chấp nhận C 15.11 Hàm chương trình nhiều tập tin Các chương trình tạo nhiều tập tin Những chương trình tạo hàm lớn, hàm chiếm tập tin Cũng biến chương trình nhiều tập tin, hàm định nghĩa static external Phạm vi hàm external sử dụng tất tập tin chương trình, cách lưu trữ mặc định cho tập tin Các hàm static nhận biết bên tập tin chương trình phạm vi khơng vượt khỏi tập tin chương trình Phần tiêu đề (header) hàm sau, static fn _type fn_name (argument list) extern fn_type fn_name (argument list) Từ khóa extern tuỳ chọn (khơng bắt buộc) lớp lưu trữ mặc định 15.12 Con trỏ đến hàm Một đặc tính mạnh mẽ C chưa đề cập, trỏ hàm Dù hàm biến, có địa vật lý nhớ nơi gán cho trỏ Một địa hàm điểm bắt đầuđi vào hàm trỏ hàm sử dụng để gọi hàm Để hiểu trỏ hàm làm việc nào, thật cần phải hiểu thật rõ hàm biên dịch gọi C Khi hàm biên dịch, mã nguồn chuyển thành mã đối tượng điểm bắt đầuđi vào hàm thiết lập Khi lời gọi thực đến hàm, lời gọi ngôn ngữ máy thực để chuyển điều khiển đến điểm bắt đầuđi vào hàm Vì vậy, trỏ chứa địa điểm bắt đầuđi vào hàm, dùng để gọi hàm Địa hàm lấy cách sử dụng tên hàm khơng có dấu ngoặc () hay đối số Chương trình sau minh họa khái niệm trỏ hàm #include #include void check(char *a, char *b, int (*cmp)()); main() { char s1[80], s2[80]; int (*p)(); p = strcmp; gets(s1); gets(s2); check(s1, s2, p); } Hàm 225 void check(char *a, char *b, int (*cmp)()) { printf(“Testing for equality \n”); if(!(*cmp)(a, b)) printf(“Equal”); else printf(“Not Equal”); } Hàm check() gọi cách truyền hai trỏ ký tự trỏ hàm Trong hàm check(), đối số khai báo trỏ ký tự hàm trỏ Chú ý cách khai báo hàm trỏ khai báo Cú pháp tương tự dùng khai báo hàm trỏ khác kiểu trả hàm Cặp dấu ngoặc () bao quanh *cmp cần thiết để chương trình biên dịch hiểu câu lệnh cách rõ ràng 226 Lập trình C Tóm tắt học  Trong C, hàm dùng để thực thi chuỗi thị nhiều lần  type_specifier xác định kiểu liệu giá trị trả hàm  Các đối số tới hàm hằng, biến, biểu thức hay hàm  Các đối số gọi đối số thực hàm gọi đối số hình thức hàm gọi  Một hàm phải khai báo hàm main(), trước định nghĩa hay sử dụng  Trong C, mặc định, tất đối số hàm truyền giá trị  Có ba loại biến bản: biến cục bộ, tham số hình thức biến tồn cục • Biến cục khai báo bên hàm • Tham số hình thức khai báo định nghĩa tham số hàm • Biến toàn cục khai báo bên tất hàm  Lớp lưu trữ định nghĩa hai đặc tính biến; thời gian sống biến tầm nhìn hay phạm vi  Các biến tự động giống biến cục  Tất biến toàn cục khai báo tập tin giống với biến khai báo extern tất tập tin  Các biến static biến cố định bên hàm tập tin chúng  Khơng giống biến tồn cục, biến tĩnh khơng nhận biết bên ngồi hàm tập tin nó, chúng trì giá trị chúng lần gọi  Nếu giá trị đặc biệt sử dụng thường xuyên, dùng lớp lưu trữ register cho  Cũng giống biến chương trình có nhiều tập tin, hàm định nghĩa static hay external  Mã lệnh liệu định nghĩa bên hàm tương tác với mã lệnh hay liệu định nghĩa hàm khác hai hàm có phạm vi khác  Một hàm định nghĩa bên hàm khác  Một nguyên mẫu hàm khai báo hàm xác địnhđể kiểu liệu đối số  Lời gọi hàm từ bên hàm khác gọi làm tổ lời gọi hàm  Một trỏ hàm dùng để gọi hàm Hàm 227 Kiểm tra tiến độ học tập Một _ đoạn chương trình chứa thực tác vụ xác địnhcụ thể Các đối số xuất cặp dấu ngoặc () gọi _ Nếu khơng có lệnh return, điều khiển chuyển đến chương trình gọi gặp dấu ngoặc đóng } khối mã lệnh Điều gọi Hàm gọi đến hàm khác có tên hàm gọi đến có tên Một khai báo hàm để xác địnhchỉ kiểu liệu đối số _ tham chiếu đến lệnh bên khối lệnh khai báo chúng nhìn thấy tồn chương trình, sử dụng mã lệnh _ định đoạn mã lệnh truy xuất đến đoạn mã lệnh khác hayhoặc liệu hay không Các đối số gọi truyền giá trị biến truyền đến hàm gọi 10 Trong _, hàm phép truy xuất vị trí nhớ thật đối số 228 Lập trình C ... nghĩa bên hàm khác  Một nguyên mẫu hàm khai báo hàm xác địnhđể kiểu liệu đối số  Lời gọi hàm từ bên hàm khác gọi làm tổ lời gọi hàm  Một trỏ hàm dùng để gọi hàm Hàm 227 Kiểm tra tiến độ học tập... truyền đến hàm đối số phép hàm gọi chương trình truy xuất biến mà phạm vi khơng vượt khỏi hàm gọi Khi trỏ truyền đến hàm, địa liệu truyền đến hàm nên hàm tự truy xuất nội dung địa Các hàm gọi nhận... số hàm cho phép liệu thay đổi hàm gọi, cho phép truyền liệu hai chiều hàm gọi hàm gọi Khi đối số hàm trỏ mảng, truyền tham chiếu tạo đối nghịch với cách truyền giá trị Các đối số hình thức hàm

Ngày đăng: 18/01/2014, 16:20

Từ khóa liên quan

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan