3 function
TRANSCRIPT
Hàm - FunctionHàm - Function
Hàm - FunctionHàm - Function
Một số nguyên tắcMột số nguyên tắc Cách khai báo và gọi thực hiệnCách khai báo và gọi thực hiện Prototype của hàmPrototype của hàm Truyền tham số cho hàmTruyền tham số cho hàm Biến toàn cục, biến cục bộ, biến static, biến thanh ghi, Biến toàn cục, biến cục bộ, biến static, biến thanh ghi,
…… Cách thức C thực hiện các lời gọi hàm – stack.Cách thức C thực hiện các lời gọi hàm – stack.
Một số nguyên tắcMột số nguyên tắc Các hàm trong NNLT C đều ngang cấp với nhau:Các hàm trong NNLT C đều ngang cấp với nhau:
Hàm không được khai báo lồng nhau.Hàm không được khai báo lồng nhau. Thứ tự khai báo không quan trọng. Thứ tự khai báo không quan trọng.
Hàm có thể nhận và xử lý nhiều tham số hoặc không có Hàm có thể nhận và xử lý nhiều tham số hoặc không có tham số nàotham số nào
Hàm có thể trả về một giá trị hoặc không.Hàm có thể trả về một giá trị hoặc không. Biến khai báo trong hàm F chỉ có giá trị trong F, không sử 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.dụng được biến này trong các hàm khác được.
Ví dụ: hàm tính xVí dụ: hàm tính xnn
double Power(double x, int n){
double result;
for(result = 1; n; n--)result *= x;
return result;}
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ọikiểu của giá trị trả về
giá trị được trả về qua lệnh return
Ví dụ: gọi thực hiện hàm PowerVí 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;
}
#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ự
Một số lỗi thường gặpMộ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;
}
#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ố
PrototypesPrototypes Dòng khai báoDòng khai báo
double Power(double, int);
được hiểu là khai báo được hiểu là khai báo prototypeprototype của hàm Power của hàm Power Được dùng khi chương trình sử dụng một hàm trước khi Được dùng khi chương trình sử dụng một hàm trước khi
khai báo.khai báo. Khai báo prototype thông báo cho trình biên dịch biết kiểu 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.của giá trị trả về và mô tả chi tiết về các tham số của hàm. Các hàm thư viện chuẩn được khai báo prototype trong các 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, …).tập tin header (stdio.h, conio.h, …). Các hàm do lập trình viên tự xây dựng phải tự khai báo Các hàm do lập trình viên tự xây dựng phải tự khai báo
prototype.prototype.
Hàm: dạng tổng quátHà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ề}
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
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;
}
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;
}
Tầm tác dụng của biếnTầm tác dụng của biến Biến toàn cục: Biến toàn cục:
Không thuộc khối Không thuộc khối nào, có tác dụng nào, có tác dụng trong toàn chương trong toàn chương trình kể từ khi khai trình kể từ khi khai báobáo
Biến cục bộ: khai Biến cục bộ: khai báo trong một khối, báo trong một khối, chỉ có tác dụng chỉ có tác dụng trong khối nàytrong khối này
compiler không chấp nhận “d”, “i”
“f” của hàm F, không phải của main
Truyền tham số cho hàmTruyền tham số cho hàm
C hỗ trợ 2 cách truyền tham số:C hỗ trợ 2 cách truyền tham số: Truyền tham số bởi giá trị (truyền giá trị - call by Truyền tham số bởi giá trị (truyền giá trị - call by
value)value) Truyền tham số bởi địa chỉ (truyền địa chỉ - call Truyền tham số bởi địa chỉ (truyền địa chỉ - call
by address)by address)
Mở rộng với C++Mở rộng với C++ Truyền tham chiếu (call by reference)Truyền tham chiếu (call by reference)
Truyền giá trịTruyền giá trị
Hàm sẽ xử lý trên bản sao của tham sốHàm sẽ xử lý trên bản sao của tham số Hàm không thể thay đổi giá trị của tham số được.Hàm không thể thay đổi giá trị của tham số được. Được dùng trong các trường hợp cần chuyển dữ liệu Đượ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ánvào bên trong hàm để xử lý, tính toán Các ví dụ trên đều dùng kiểu truyền tham số bởi giá trịCác ví dụ trên đều dùng kiểu truyền tham số bởi giá trị Ví dụ hàm có sẵn của C truyền giá trị:Ví dụ hàm có sẵn của C truyền giá trị:
float sqrt(float);float sqrt(float); double pow(double, double);double pow(double, double);
Truyền giá trị - ví dụTruyền giá trị - ví dụ#include <stdio.h>void change(int v);
int main(){
int var = 5;change(var);printf("main: var = %i\n", var);return 0;
}
void change(int v){
v *= 100;printf("change: v = %i\n", v);
}
#include <stdio.h>void change(int v);
int main(){
int var = 5;change(var);printf("main: var = %i\n", var);return 0;
}
void change(int v){
v *= 100;printf("change: v = %i\n", v);
}
change: v = 500main: var = 5
change: v = 500main: var = 5
hàm change không thay đổi giá trị của “var”
Truyền địa chỉTruyền địa chỉ
Hàm sẽ xử lý trên chính tham số nhờ vào địa chỉ Hàm sẽ xử lý trên chính tham số nhờ vào địa chỉ của chúngcủa chúng
Hàm có thể thay đổi giá trị của tham số.Hàm có thể thay đổi giá trị của tham số. Được dùng trong các trường hợp cần chuyển dữ liệu Đượ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 là kết quả xử lý được bên trong hàm ra “ngoài”“ngoài” cho cho các hàm khác sử dụng. các hàm khác sử dụng.
Ví dụ hàm có sẵn của C truyền địa chỉ:Ví dụ hàm có sẵn của C truyền địa chỉ:int scanf(const char *format, adr1, adr2, …);int scanf(const char *format, adr1, adr2, …);
functionfunctioninputsinputs outputsoutputs
Truyền địa chỉ - ví dụTruyền địa chỉ - ví dụ#include <stdio.h>void change(int *v);
int main(){
int var = 5;change(&var);printf("main: var = %i\n", var);return 0;
}
void change(int *v){
(*v) *= 100;printf("change: *v = %i\n", (*v));
}
#include <stdio.h>void change(int *v);
int main(){
int var = 5;change(&var);printf("main: var = %i\n", var);return 0;
}
void change(int *v){
(*v) *= 100;printf("change: *v = %i\n", (*v));
}
change: *v = 500main: var = 500
change: *v = 500main: 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
Truyền tham chiếuTruyền tham chiếu
Hàm sẽ xử lý trên bản sao tham số và cập nhật lại bản 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.chính ngay trước khi hàm kết thúc.
Hàm có thể thay đổi giá trị của tham số.Hàm có thể thay đổi giá trị của tham số. Được dùng trong các trường hợp cần chuyển dữ liệu là Đượ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 kết quả xử lý được bên trong hàm ra “ngoài”“ngoài” cho các cho các hàm khác sử dụng. hàm khác sử dụng.
Chỉ áp dụng được với các trình biên dịch C++Chỉ áp dụng được với các trình biên dịch C++
Truyền tham chiếu - ví dụTruyền tham chiếu - ví dụ#include <stdio.h>void change(int &v);
int main(){
int var = 5;change(var);printf("main: var = %i\n", var);return 0;
}
void change(int &v){
v *= 100;printf("change: v = %i\n", v);
}
#include <stdio.h>void change(int &v);
int main(){
int var = 5;change(var);printf("main: var = %i\n", var);return 0;
}
void change(int &v){
v *= 100;printf("change: v = %i\n", v);
}
change: v = 500main: var = 500
change: v = 500main: var = 500
v: tham số tham chiếu, khai báo với dấu &
truyền “var” vào hàm change
Truyền tham số - ví dụ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("%i %i %i\n", x, y, z);return 0;
}void function(int a, int *b, int &c){
a *= 2;(*b) += a;c = a + (*b);printf("%i %i %i\n", a, *b, c);
}
#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("%i %i %i\n", x, y, z);return 0;
}void function(int a, int *b, int &c){
a *= 2;(*b) += a;c = a + (*b);printf("%i %i %i\n", a, *b, c);
}
6 10 163 10 16
6 10 163 10 16
mainmain
functionfunction
aa bb cc
Phương thức trao đổi dữ liệuPhương thức trao đổi dữ liệu C dùng 1 stack để lưu trữ các biến cục bộ và các chuyển 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ệncác tham số cho hàm với mỗi lần gọi hàm thực hiện Hàm gọi (O) cất các tham số vào stack.Hàm gọi (O) cất các tham số vào stack. Gọi thực hiện hàm được gọi (F).Gọi thực hiện hàm được gọi (F). F nhận lấy các tham số từ stackF nhận lấy các tham số từ stack F tạo các biến cục bộ ứng với các tham số trên stackF tạo các biến cục bộ ứng với các tham số trên stack Khi kết thúc, F cập nhật giá trị các tham số (ref) và trả điều Khi kết thúc, F cập nhật giá trị các tham số (ref) và trả điều
khiển cho Okhiển cho O O nhận lấy các giá trị mới của tham số cũng như giá trị trả O nhận lấy các giá trị mới của tham số cũng như giá trị trả
vềvề
#include <stdio.h>double power(int, int);int main(void){
int x = 2;double d;d = power(x, 5);printf("%lf\n", d);return 0;
}double power(int n, int p){
double result = n;while(--p > 0)
result *= n;return result;
}
#include <stdio.h>double power(int, int);int main(void){
int x = 2;double d;d = power(x, 5);printf("%lf\n", d);return 0;
}double power(int n, int p){
double result = n;while(--p > 0)
result *= n;return result;
}
main: x2
main: d?
power: p5
power: n2
power: result32.0
Phương thức trao đổi dữ liệuPhương thức trao đổi dữ liệu
32.0
Bài đọc thêm: Bài đọc thêm: tổ chức dữ liệutổ chức dữ liệu Dữ liệu trong chương trình được lưu trữ trong các Dữ liệu trong chương trình được lưu trữ trong các
biến.biến. Khi hàm được gọi thực hiện, các biến cục bộ sẽ 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 được khởi tạo trên vùng nhớ stack và tự động bị hủy khi hàm kết thúc.khi hàm kết thúc.
Các biến toàn cục sẽ được tạo trên vùng nhớ phân 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 đ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 gọi thực hiện, tự động bị hủy khi chương trình kết thúc.thúc.
Có thể sử dụng các từ khóa để chỉ định vị trí của Có thể sử dụng các từ khóa để chỉ định vị trí của biến:biến:
autoauto - stack (default)- stack (default)
staticstatic - data segment- data segment
registerregister - thanh ghi của CPU- thanh ghi của CPU
Dữ liệu còn có thể được đặt trong vùng nhớ heap.Dữ liệu còn có thể được đặt trong vùng nhớ heap.
HeapHeap
Data Data segmentsegment
StackStack
Tóm lượcTóm lược
Khai báo và gọi thực hiện hàmKhai báo và gọi thực hiện hàm Khai báo prototypesKhai báo prototypes Tầm tác dụng của biếnTầm tác dụng của biến Truyền tham số cho hàmTruyền tham số cho hàm Vấn đề tổ chức dữ liệu trong chương trìnhVấn đề tổ chức dữ liệu trong chương trình