3 Function

1,612 views

Published on

0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,612
On SlideShare
0
From Embeds
0
Number of Embeds
8
Actions
Shares
0
Downloads
55
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

3 Function

  1. 1. Hàm - Function
  2. 2. Hàm - Function <ul><li>Một số nguyên tắc </li></ul><ul><li>Cách khai báo và gọi thực hiện </li></ul><ul><li>Prototype của hàm </li></ul><ul><li>Truyền tham số cho hàm </li></ul><ul><li>Biến toàn cục, biến cục bộ, biến static, biến thanh ghi, … </li></ul><ul><li>Cách thức C thực hiện các lời gọi hàm – stack. </li></ul>
  3. 3. Một số nguyên tắc <ul><li>Các hàm trong NNLT C đều ngang cấp với nhau: </li></ul><ul><ul><li>Hàm không được khai báo lồng nhau. </li></ul></ul><ul><ul><li>Thứ tự khai báo không quan trọng. </li></ul></ul><ul><li>Hàm có thể nhận và xử lý nhiều tham số hoặc không có tham số nào </li></ul><ul><li>Hàm có thể trả về một giá trị hoặc không. </li></ul><ul><li>Biến khai báo trong hàm F chỉ có giá trị trong F, không sử dụng được biến này trong các hàm khác được. </li></ul>
  4. 4. Ví dụ: hàm tính x n double Power(double x, int n) { double result; for(result = 1; n; n--) result *= x; return result; } nhận vào 2 tham số khi được gọi kiểu của giá trị trả về giá trị được trả về qua lệnh return
  5. 5. Ví dụ: gọi thực hiện hàm Power #include <stdio.h> double Power(double, int); int main() { double m = Power(2, 3); printf(“3.5 ^ 4 = %lf”, Power(3.5, 4)); return 0; } Chỉ thị cho chương trình biết prototype của hàm Power 3.5 và 4: 2 tham số thực sự
  6. 6. Một số lỗi thường gặp #include <stdio.h> int main() { int m = Power(2, 3); printf(“3.5 ^ 4 = %lf”, Power(4)); return 1.0; } Compiler không hiểu được hàm Power giá trị trả về không khớp kiểu hàm Power thiếu tham số
  7. 7. Prototypes <ul><li>Dòng khai báo </li></ul><ul><li>double Power(double, int); </li></ul><ul><li>được hiểu là khai báo prototype của hàm Power </li></ul><ul><li>Được dùng khi chương trình sử dụng một hàm trước khi khai báo. </li></ul><ul><li>Khai báo prototype thông báo cho trình biên dịch biết kiểu của giá trị trả về và mô tả chi tiết về các tham số của hàm. </li></ul><ul><li>Các hàm thư viện chuẩn được khai báo prototype trong các tập tin header (stdio.h, conio.h, …). </li></ul><ul><li>Các hàm do lập trình viên tự xây dựng phải tự khai báo prototype. </li></ul>
  8. 8. Hàm: dạng tổng quát kiểu trả về tên hàm( danh sách tham số hình thức ) { //khai báo các biến của hàm //các lệnh thực thi return giá trị trả về ; //hàm void không có giá trị trả về } header của hàm thân (body) hàm
  9. 9. Tầm tác dụng của biến <ul><li>Biến toàn cục: Không thuộc khối nào, có tác dụng trong toàn chương trình kể từ khi khai báo </li></ul><ul><li>Biến cục bộ: khai báo trong một khối, chỉ có tác dụng trong khối này </li></ul>float g=6.5; void main() { int i = 5, j, k = 2; float f = 2.8F ; d = 3.7; } void F(int v) { double d, e = 0.0, f; i++; g--; f = 0.0; } compiler không chấp nhận “d”, “i” “ f” của hàm F, không phải của main
  10. 10. Truyền tham số cho hàm <ul><li>C hỗ trợ 2 cách truyền tham số: </li></ul><ul><ul><li>Truyền tham số bởi giá trị (truyền giá trị - call by value) </li></ul></ul><ul><ul><li>Truyền tham số bởi địa chỉ (truyền địa chỉ - call by address) </li></ul></ul><ul><li>Mở rộng với C++ </li></ul><ul><ul><li>Truyền tham chiếu (call by reference) </li></ul></ul>
  11. 11. Truyền giá trị <ul><li>Hàm sẽ xử lý trên bản sao của tham số </li></ul><ul><li>Hàm không thể thay đổi giá trị của tham số được. </li></ul><ul><li>Được dùng trong các trường hợp cần chuyển dữ liệu vào bên trong hàm để xử lý, tính toán </li></ul><ul><li>Các ví dụ trên đều dùng kiểu truyền tham số bởi giá trị </li></ul><ul><li>Ví dụ hàm có sẵn của C truyền giá trị: </li></ul><ul><ul><li>float sqrt(float); </li></ul></ul><ul><ul><li>double pow(double, double); </li></ul></ul>
  12. 12. Truyền giá trị - ví dụ #include <stdio.h> void change(int v); int main() { int var = 5; change(var); printf(&quot;main: var = %i &quot;, var); return 0; } void change(int v) { v *= 100; printf(&quot;change: v = %i &quot;, v); } change: v = 500 main: var = 5 hàm change không thay đổi giá trị của “var”
  13. 13. Truyền địa chỉ <ul><li>Hàm sẽ xử lý trên chính tham số nhờ vào địa chỉ của chúng </li></ul><ul><li>Hàm có thể thay đổi giá trị của tham số. </li></ul><ul><li>Được dùng trong các trường hợp cần chuyển dữ liệu là kết quả xử lý được bên trong hàm ra “ngoài” cho các hàm khác sử dụng. </li></ul>Ví dụ hàm có sẵn của C truyền địa chỉ: int scanf(const char *format, adr1, adr2, …); function inputs outputs
  14. 14. Truyền địa chỉ - ví dụ #include <stdio.h> void change(int *v); int main() { int var = 5; change(&var); printf(&quot;main: var = %i &quot;, var); return 0; } void change(int *v) { (*v) *= 100; printf(&quot;change: *v = %i &quot;, (*v)); } change: *v = 500 main: var = 500 v: tham số địa chỉ của số int, khai báo với dấu * truyền địa chỉ của “var” vào hàm change
  15. 15. Truyền tham chiếu <ul><li>Hàm sẽ xử lý trên bản sao tham số và cập nhật lại bản chính ngay trước khi hàm kết thúc. </li></ul><ul><li>Hàm có thể thay đổi giá trị của tham số. </li></ul><ul><li>Được dùng trong các trường hợp cần chuyển dữ liệu là kết quả xử lý được bên trong hàm ra “ngoài” cho các hàm khác sử dụng. </li></ul><ul><li>Chỉ áp dụng được với các trình biên dịch C++ </li></ul>
  16. 16. Truyền tham chiếu - ví dụ #include <stdio.h> void change(int &v); int main() { int var = 5; change(var); printf(&quot;main: var = %i &quot;, var); return 0; } void change(int &v) { v *= 100; printf(&quot;change: v = %i &quot;, v); } change: v = 500 main: var = 500 v: tham số tham chiếu, khai báo với dấu & truyền “var” vào hàm change
  17. 17. Truyền tham số - ví dụ #include <stdio.h> void function(int a, int *b, int &c); int main() { int x = 3, y = 4, z = 5; function(x, &y, z); printf(&quot;%i %i %i &quot;, x, y, z); return 0; } void function(int a, int *b, int &c) { a *= 2; (*b) += a; c = a + (*b); printf(&quot;%i %i %i &quot;, a, *b, c); } 6 10 16 3 10 16 main function a b c
  18. 18. Phương thức trao đổi dữ liệu <ul><li>C dùng 1 stack để lưu trữ các biến cục bộ và các chuyển các tham số cho hàm với mỗi lần gọi hàm thực hiện </li></ul><ul><li>Hàm gọi (O) cất các tham số vào stack. </li></ul><ul><li>Gọi thực hiện hàm được gọi (F). </li></ul><ul><li>F nhận lấy các tham số từ stack </li></ul><ul><li>F tạo các biến cục bộ ứng với các tham số trên stack </li></ul><ul><li>Khi kết thúc, F cập nhật giá trị các tham số (ref) và trả điều khiển cho O </li></ul><ul><li>O nhận lấy các giá trị mới của tham số cũng như giá trị trả về </li></ul>
  19. 19. Phương thức trao đổi dữ liệu #include <stdio.h> double power(int, int); int main(void) { int x = 2; double d; d = power(x, 5); printf(&quot;%lf &quot;, d); return 0; } double power(int n, int p) { double result = n; while(--p > 0) result *= n; return result; } main: x 2 main: d ? power: p 5 power: n 2 power: result 32.0 32.0
  20. 20. Bài đọc thêm: tổ chức dữ liệu <ul><li>Dữ liệu trong chương trình được lưu trữ trong các biến. </li></ul><ul><li>Khi hàm được gọi thực hiện, các biến cục bộ sẽ được khởi tạo trên vùng nhớ stack và tự động bị hủy khi hàm kết thúc. </li></ul><ul><li>Các biến toàn cục sẽ được tạo trên vùng nhớ phân đoạn dữ liệu (data segment) khi chương trình được gọi thực hiện, tự động bị hủy khi chương trình kết thúc. </li></ul><ul><li>Có thể sử dụng các từ khóa để chỉ định vị trí của biến: </li></ul><ul><li>auto - stack (default) </li></ul><ul><li>static - data segment </li></ul><ul><li>register - thanh ghi của CPU </li></ul><ul><li>Dữ liệu còn có thể được đặt trong vùng nhớ heap. </li></ul>Heap Data segment Stack
  21. 21. Tóm lược <ul><li>Khai báo và gọi thực hiện hàm </li></ul><ul><li>Khai báo prototypes </li></ul><ul><li>Tầm tác dụng của biến </li></ul><ul><li>Truyền tham số cho hàm </li></ul><ul><li>Vấn đề tổ chức dữ liệu trong chương trình </li></ul>

×