Mục tiêu của giáo trình Lập trình căn bản là phân tích chương trình: xác định nhiệm vụ chương trình (phải làm gì), xác định dữ liệu và cấu trúc dữ liệu của hệ thống. Phân tích và xây dựng thuật toán; Thiết kế chương trình: tìm giải pháp kỹ thuật (làm thế nào) đối với những công việc đã xác định trong giai đoạn phân tích. Mời các bạn cùng tham khảo nội dung phần 2 giáo trình dưới đây!
Trang 1CHƯƠNG 5 HÀM Giới thiệu
Một chương trình viết trong ngôn ngữ C là một dãy các hàm Hàm chia các bài toán lớn thành các công việc nhỏ hơn, giúp thực hiện những công việc lặp lại nào đó một cách nhanh chóng mà không phải viết lại đoạn chương trình
Bài này sẽ trình bày cách viết chương trình theo cấu trúc hàm, cách truyền tham
số cho hàm trong lập trình, sử dụng đệ qui trong lập trình
Mục tiêu
- Viết chương trình theo cấu trúc hàm
- Vận dụng các cách truyền tham số cho hàm trong lập trình
- Sử dụng đệ qui trong lập trình
Nội dung chính
I KHÁI NIỆM
Một chương trình viết trong ngôn ngữ C là một dãy các hàm, trong đó có một
hàm chính (hàm main()) Hàm chia các bài toán lớn thành các công việc nhỏ hơn, giúp thực hiện những công việc lặp lại nào đó một cách nhanh chóng mà không phải viết lại đoạn chương trình Thứ tự các hàm trong chương trình là bất kỳ, song chương
trình bao giờ cũng đi thực hiện từ hàm main()
II KHAI BÁO HÀM
type tên hàm (khai báo các đối số)
Trang 2Kiểu đối 1 tên đối 1, kiểu đối 2 tên đối 2, , kiểu đối n tên đối n
Thân hàm có thể sử dụng một câu lệnh return, có thể dùng nhiều câu lệnh return
ở các chỗ khác nhau, và cũng có thể không sử dụng câu lệnh này
Dạng tổng quát của nó là:
return [biểu thức];
Giá trị của biểu thức trong câu lệnh return sẽ được gán cho hàm
Ví dụ: Xét bài toán: Tìm giá trị lớn nhất của ba số mà giá trị mà giá trị của
chúng được đưa vào bàn phím
Xây dựng chương trình và tổ chức thành hai hàm: Hàm main() và hàm max3s Nhiệm vụ của hàm max3s là tính giá trị lớn nhất của ba số đọc vào, giả sử là a,b,c Nhiệm vụ của hàm main() là đọc ba giá trị vào từ bàn phím, rồi dùng hàm max3s để tính như trên, rồi đưa kết quả ra màn hình
Chương trình được viết như sau:
Trang 3if (max<b) max=b;
if (max<c) max=c;
return(max);
} /* Kết thúc hàm max3s*/
Quy tắc hoạt động của hàm:
Một cách tổng quát lời gọi hàm có dạng sau:
tên hàm ([Danh sách các tham số thực])
Số các tham số thực tế thay vào trong danh sách các đối phải bằng số tham số hình thức và lần lượt chúng có kiểu tương ứng với nhau
Khi gặp một lời gọi hàm thì nó sẽ bắt đầu được thực hiện Nói cách khác, khi máy gặp lời gọi hàm ở một vị trí nào đó trong chương trình, máy sẽ tạm dời chỗ đó và chuyển đến hàm tương ứng Quá trình đó diễn ra theo trình tự sau:
Cấp phát bộ nhớ cho các biến cục bộ
Gán giá trị của các tham số thực cho các đối tương ứng
Thực hiện các câu lệnh trong thân hàm
Khi gặp câu lệnh return hoặc dấu } cuối cùng của thân hàm thì máy sẽ xoá các đối, biến cục bộ và ra khỏi hàm
Nếu trở về từ một câu lệnh return có chứa biểu thức thì giá trị của biểu thức được gán cho hàm Giá trị của hàm sẽ được sử dụng trong các biểu thức chứa nó
Các tham số thực, các đối và biến cục bộ:
Do đối và biến cục bộ đều có phạm vi hoạt động trong cùng một hàm nên đối
và biến cục bộ cần có tên khác nhau
Đối và biến cục bộ đều là các biến tự động Chúng được cấp phát bộ nhớ khi hàm được xét đến và bị xoá khi ra khỏi hàm nên ta không thể mang giá trị của đối ra khỏi hàm
Đối và biến cục bộ có thể trùng tên với các đại lượng ngoài hàm mà không gây
ra nhầm lẫn nào
Khi một hàm được gọi tới, việc đầu tiên là giá trị của các tham số thực được gán cho các đối (trong ví dụ trên hàm max3s, các tham số thực là x,y,z, các đối tương ứng là a,b,c) Như vậy các đối chính là các bản sao của các tham số thực Hàm chỉ làm việc trên các đối
Các đối có thể bị biến đổi trong thân hàm, còn các tham số thực thì không bị thay đổi
Chú ý:
Trang 4Khi hàm khai báo không có kiểu ở trước nó thì nó được mặc định là kiểu int
Không nhất thiết phải khai báo nguyên mẫu hàm Nhưng nói chung nên có vì
nó cho phép chương trình biên dịch phát hiện lỗi khi gọi hàm hay tự động việc chuyển dạng
Nguyên mẫu của hàm thực chất là dòng đầu tiên của hàm thêm vào dấu ; Tuy nhiên trong nguyên mẫu có thể bỏ tên các đối
Hàm thường có một vài đối Ví dụ như hàm max3s có ba đối là a,b,c cả ba đối này đều có giá trị float Tuy nhiên, cũng có hàm không đối như hàm main
Hàm thường cho ta một giá trị nào đó Lẽ dĩ nhiên giá trị của hàm phụ thuộc vào giá trị các đối
III KẾT QUẢ TRẢ VỀ CỦA HÀM
- Hàm có thể nhận một hoặc nhiều giá trị đầu vào và trả về một giá trị thuộc kiểu
dữ liệu nào đó Kiểu dữ liệu được trả về của hàm được khai báo ở type
- Hàm có thề có hoặc không có giá trị trả về Nếu hàm không có nhận giá trị đầu
vào và không có giá trị trả về thì ở khai báo bằng từ khóa void
- Các biến hoặc biểu thức cung cấp giá trị đầu vào cho hàm được gọi là đối số Hàm có thể thay đổi các đối số của nó
IV CÁCH TRUYỀN THAM SỐ CHO HÀM
Cho đến nay, trong tất cả các hàm chúng ta đã biết, tất cả các tham số truyền cho
hàm đều được truyền theo giá trị Điều này có nghĩa là khi chúng ta gọi hàm với các tham số, những gì chúng ta truyền cho hàm là các giá trị chứ không phải bản thân các
biến Ví dụ, giả sử chúng ta gọi hàm addition như sau:
int x=5, y=3, z;
z = addition ( x , y );
Trong trường hợp này khi chúng ta gọi hàm addition thì các giá trị 5 and 3 được
truyền cho hàm, không phải là bản thân các biến
Điều đáng nói ở đây là khi chúng ta thay đổi giá trị của các biến a hay b bên trong hàm thì các biến x và y vẫn không thay đổi vì chúng đâu có được truyền cho
hàm chỉ có giá trị của chúng được truyền mà thôi
Trang 5Hãy xét trường hợp cần thao tác với một biến ngoài ở bên trong một hàm Vì
vậy ta sẽ phải truyền tham số dưới dạng tham số biến như ở trong hàm duplicate
trong ví dụ dưới đây:
// passing parameters by reference
tham số biến chứ không phải tham số giá trị
Khi truyền tham số dưới dạng tham số biến chúng ta đang truyền bản thân biến
đó và bất kì sự thay đổi nào mà chúng ta thực hiện với tham số đó bên trong hàm sẽ ảnh hưởng trực tiếp đến biến đó
Trang 6Trong ví dụ trên, chúng ta đã liên kết a, b và c với các tham số khi gọi hàm (x, y
và z) và mọi sự thay đổi với a bên trong hàm sẽ ảnh hưởng đến giá trị của x và hoàn toàn tương tự với b và y, c và z
Kiểu khai báo tham số theo dạng tham số biến sử dụng dấu và (&) chỉ có trong
C++ Trong ngôn ngữ C chúng ta phải sử dụng con trỏ để làm việc tương tự như thế Truyền tham số dưới dạng tham số biến cho phép một hàm trả về nhiều hơn một
Khi hàm gọi đệ qui đến chính nó, thì mỗi lần gọi máy sẽ tạo ra một tập các biến cục bộ mới hoàn toàn độc lập với tập các biến cục bộ đã được tạo ra trong các lần gọi trước
Để minh hoạ chi tiết những điều trên, ta xét một ví dụ về tính giai thừa của số nguyên dương n Khi không dùng phương pháp đệ qui hàm có thể được viết như sau:
long int gt(int n) /* Tính n! với n>=0*/
{
long int gtphu=1;
int i;
for (i=1;i<=n;++i) gtphu*=i;
long int gtdq(int n) {
if (n==0 || n==1) return 1;
Trang 7else return(n*gtdq(n-1));
n*gtdq(n-1) (*)
Để tính biểu thức trên, máy cần gọi chính hàm gtdq vì thế lần gọi thứ hai sẽ thực hiện Máy sẽ tạo ra đối n mới, ta gọi đó là n thứ hai Giá trị của n-1 ở đây lại là đối của hàm , đƣợc truyền cho hàm và hiểu là n thứ hai, do vậy n thứ hai có giá trị là
2 Bây giờ, do n thứ hai vẫn chƣa thoả mãn điều kiện if nên máy lại tiếp tục tính biểu thức:
n*gtdq(n-1) (**) Biểu thức trên lại gọi hàm gtdq lần thứ ba Máy lại tạo ra đối n lần thứ ba và ở đây n thứ ba có giá trị bằng 1 Đối n=1 thứ ba lại đƣợc truyền cho hàm, lúc này điều kiện trong lệnh if đƣợc thoả mãn, máy đi thực hiện câu lệnh:
return 1=gtdq(1) (***) Bắt đầu từ đây, máy sẽ thực hiện ba lần ra khỏi hàm gtdq Lần ra khỏi hàm thứ nhất ứng với lần vào thứ ba Kết quả là đối n thứ ba đƣợc giải phóng, hàm gtdq(1) cho giá trị là 1 và máy trở về xét giá trị biểu thức
n*gtdq(1) đây là kết quả của (**)
ở đây, n là n thứ hai và có giá trị bằng 2 Theo câu lệnh return, máy sẽ thực hiện lần ra khỏi hàm lần thứ hai, đối n thứ hai sẽ đƣợc giải phóng, kết quả là biểu thức trong (**)
có giá trị là 2.1 Sau đó máy trở về biểu thức (*) lúc này là:
n*gtdq(2)=n*2*1
Trang 8n lại hiểu là thứ nhất, nó có giá trị bằng 3, do vậy giá trị của biểu thức trong (*) là 3.2.1=6 Chính giá trị này được sử dụng trong câu lệnh printf của hàm main() nên kết quả in ra trên màn hình là:
3!=6
Chú ý:
Hàm đệ qui so với hàm có thể dùng vòng lặp thì đơn giản hơn, tuy nhiên với máy tính khi dùng hàm đệ qui sẽ dùng nhiều bộ nhớ trên ngăn xếp và có thể dẫn đến tràn ngăn xếp Vì vậy khi gặp một bài toán mà có thể có cách giải lặp (không dùng đệ qui) thì ta nên dùng cách lặp này Song vẫn tồn tại những bài toán chỉ có thể giải bằng
đệ qui
2 Các bài toán có thể dùng đệ qui
Phương pháp đệ qui thường áp dụng cho các bài toán phụ thuộc tham số có hai đặc điểm sau:
Bài toán dễ dàng giải quyết trong một số trường hợp riêng ứng với các giá trị đặc biệt của tham số Người ta thường gọi là trường hợp suy biến
Trong trường hợp tổng quát, bài toán có thể qui về một bài toán cùng dạng nhưng giá trị tham số thì bị thay đổi Sau một số hữu hạn bước biến đổi dệ qui nó sẽ dẫn tới trường hợp suy biến
Bài toán tính n giai thừa nêu trên thể hiện rõ nét đặc điểu này
Trang 9Trong trường hợp suy biến, khi a=b thì USCLN của a và b chính là giá trị của chúng
Trang 10putchar(n%10+'0');
}
BÀI TẬP
1 Sử dụng hàm viết lại các chương trình đã thực hiện ở các chương trước
2 Sử dụng hàm viết chương trình tính an (a: thực, n: nguyên dương) sử dụng đệ qui và không đệ qui
3 Tính phần tử thứn theo công thức truy hồi (đệ qui và không đệ qui)
Phần tử Fibonaci: F1=F2=1
Fn= Fn-1 + Fn-2 với n>2
Trang 11CHƯƠNG 6 MẢNG Giới thiệu
Bài này sẽ trình bày cách khai báo và khởi tạo mảng, sử dụng mảng trong lập trình, sử dụng mảng làm tham số trong các bài toán
Một mảng là một tập hợp các phần tử dữ liệu có cùng kiểu Mỗi phần tử được
lưu trữ ở các vị trí kế tiếp nhau trong bộ nhớ chính Những phần tử này được gọi là
phần tử mảng
Mỗi phần tử của mảng được định danh bằng một chỉ mục hoặc chỉ số gán cho
nó Chiều của mảng được xác định bằng số chỉ số cần thiết để định danh duy nhất mỗi phần tử Một chỉ số là một số nguyên dương được bao bằng dấu ngoặc vuông [ ] đặt ngay sau tên mảng, không có khoảng trắng ở giữa Một chỉ số chứa các giá trị nguyên bắt đầu bằng 0 Vì vậy, một mảng player với 11 phần tử được biểu diễn như
sau:
player[0], player[1], player[2], , player[10]
II KHAI BÁO MẢNG
Một mảng có một vài đặc tính riêng biệt và phải được khai báo khi sử dụng chúng Những đặc tính này bao gồm:
Lớp lưu trữ
Kiểu dữ liệu của các phần tử mảng
Tên mảng – xác định vị trí phần tử đầu tiên của mảng
Kích thước mảng - một hằng số có giá trị nguyên dương
Một mảng được khai báo giống như cách khai báo một biến, ngoại trừ tên mảng được theo sau bởi một hoặc nhiều biểu thức, được đặt trong dấu ngoặc vuông [] xác định chiều dài của mảng Cú pháp tổng quát khai báo một mảng như sau:
lớp_lưu_trữ kiểu_dữ_liệu tên_mảng[biểu_thức_kích_thước]
Trang 12Ở đây, biểu_thức_kích_thước là một biểu thức xác định số phần tử trong mảng và phải định ra một trị nguyên dương Lớp_lưu_trữ là một tùy chọn Mặc định lớp automatic được dùng cho mảng khai báo bên trong một hàm hoặc một khối lệnh,
và lớp external được dùng cho mảng khai báo bên ngoài một hàm Vì vậy mảng
player được khai báo như sau:
int player[11];
Nên nhớ rằng, trong khi khai báo mảng, kích thước của mảng sẽ là 11, tuy nhiên các chỉ số của từng phần tử bên trong mảng sẽ là từ 0 đến 10
Các qui tắc đặt tên mảng là giống với qui tắc đặt tên biến Một tên mảng và một tên
biến không được giống nhau, nó dẫn đến sự nhập nhằng Nếu một sự khai báo như
vậy xuất hiện trong chương trình, trình biên dịch sẽ hiển thị thông báo lỗi
Một vài qui tắc với mảng:
Tất cả các phần tử của một mảng có cùng kiểu Điều này có nghĩa là, nếu
một mảng được khai báo kiểu int, nó không thể chứa các phần tử có kiểu khác
Mỗi phần tử của mảng có thể được sử dụng bất cứ nơi nào mà một biến được cho phép hay được yêu cầu
Một phần tử của mảng có thể được tham chiếu đến bằng cách sử dụng một biến hoặc một biểu thức nguyên Sau đây là các tham chiếu hợp lệ:
player[i]; /*Ở đó i là một biến, tuy nhiên cần phải chú ý rằng i nằm trong miền
giới hạn của chỉ số đã được khai báo cho mảng player*/
player[3] = player[2] + 5;
player[0] += 2;
player[i / 2 + 1];
Kiểu dữ liệu của mảng có thể là int, char, float, hoặc double
III KHỞI TẠO MẢNG
Các mảng không được khởi tạo tự động, trừ khi mỗi phần tử mảng được gán một giá trị riêng lẻ Không nên dùng các mảng trước khi có sự khởi tạo thích hợp Điều này là bởi vì không gian lưu trữ của mảng không được khởi tạo tự động, do đó dễ gây
ra kết quả không lường trước Mỗi khi các phần tử của một mảng chưa khởi tạo được
sử dụng trong các biểu thức toán học, các giá trị đã tồn tại sẵn trong ô nhớ sẽ được sử dụng, các giá trị này không đảm bảo rằng có cùng kiểu như khai báo của mảng, trừ khi các phần tử của mảng được khởi tạo một cách rõ ràng Điều này đúng không chỉ cho các mảng mà còn cho các biến thông thường
Trong đoạn mã lệnh sau, các phần tử của mảng được gán giá trị bằng các dùng
vòng lặp for
Trang 13int ary[20], i;
for(i=0; i<20; i++)
ary[i] = 0;
Khởi tạo một mảng sử dụng vòng lặp for có thể được thực hiện với một hằng giá
trị, hoặc các giá trị được sinh ra từ một cấp số cộng
Một vòng lặp for cũng có thể được sử dụng để khởi tạo một mảng các ký tự như
sau:
Ví dụ :
#include <stdio.h>
void main() {
char alpha[26];
int i, j;
for(i = 65, j = 0; i < 91; i++, j++) {
alpha[j] = i;
printf(“The character now assigned is %c\n”, alpha[j]);
} getchar();
} Một phần kết quả của chương trình trên như sau:
The character now assigned is A
The character now assigned is B
The character now assigned is C
Chương trình trên gán các mã ký tự ASCII cho các phần tử của mảng alpha Kết quả là khi in với định dạng %c, một chuỗi các ký tự được xuất ra màn hình Các
mảng cũng có thể được khởi tạo khi khai báo Điều này được thực hiện bằng việc gán
tên mảng với một danh sách các giá trị phân cách nhau bằng dấu phẩy (,) đặt trong cặp dấu ngoặc nhọn {} Các giá trị trong cặp dấu ngoặc nhọn {} được gán cho các
phần tử trong mảng theo đúng thứ tự xuất hiện
Trang 14Ví dụ:
int deci[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
static float rates[4] = {0.0, -2.5, 13.75, 18.0};
char company[5] = {„A‟, „P‟, „P‟, „L‟, „E‟};
int marks[100] = {15, 13, 11, 9}
Các giá trị khởi tạo của mảng phải là các hằng, không thể là biến hoặc các biểu thức Một vài phần tử đầu tiên của mảng sẽ được khởi tạo nếu số lượng giá trị khởi tạo là ít hơn số phần tử mảng được khai báo Các phần tử còn lại sẽ được khởi tạo giá
trị 0 Ví dụ, trong mảng marks sau khi có sự khởi tạo như trên, bốn phần tử đầu tiên
(từ 0 đến 3) tương ứng được khởi tạo là 15, 13, 11 và 9 Các phần tử còn lại có giá trị
0 Không thể chỉ khởi tạo các phần tử từ 1 đến 4, hoặc từ 2 đến 4, hay từ 2 đến 5 khi
sự khởi tạo được thực hiện tại thời điểm khai báo Trong C không có khả năng lặp lại
sự khởi tạo giá trị
Trong trường hợp sự khởi tạo là tường minh, lớp extern hoặc static, các phần tử của mảng được đảm bảo khởi tạo là 0 (không giống lớp auto)
Không cần thiết khai báo kích thước của mảng đang được khởi tạo Nếu kích thước của mảng được bỏ qua khi khai báo, trình biên dịch sẽ xác định kích thước của mảng bằng cách đếm các giá trị đang được khởi tạo Ví dụ, sự khai báo mảng
external sau đây sẽ chỉ định kích thước của mảng ary là 5 vì có 5 giá trị khởi tạo
int ary[] = {1, 2, 3, 4, 5};
IV DÙNG MẢNG LÀM THAM SỐ
Trong C, khi một mảng được truyền vào hàm như một tham số, thì chỉ có địa chỉ của mảng được truyền vào Tên mảng không kèm theo chỉ số là địa chỉ của mảng Đoạn mã dưới đây mô tả cách truyền địa chỉ của mảng ary cho hàm fn_ary():
void main()
{ int ary[10];
fn_ary(ary);
}
Nếu tham số của hàm là mảng một chiều thì tham số có thể được khai báo theo một trong các cách sau:
fn_ary (int ary [10]) /* sized array */
Trang 15{
: }
hoặc
fn_arry (int ary []) /*unsized array */
{
: }
Cả hai khai báo ở trên đều cho cùng kết quả Kiểu thứ nhất sử dụng cách khai báo mảng chuẩn, chỉ rõ ra kích thước của mảng Kiểu thứ hai chỉ ra rằng tham số là
một mảng kiểu int có kích thước bất kỳ
Chương trình sau đây nhận các số vào một mảng số nguyên Sau đó mảng này sẽ được truyền vào hàm sum_arr() Hàm sẽ tính toán và trả về tổng của các số nguyên trong mảng
Ví dụ 8:
#include <stdio.h>
void main()
{
int num[5], ctr, sum = 0;
int sum_arr(int num_arr[]); /* Function declaration */
Trang 16sum = sum_arr(num); /* Invokes the function */
printf("\nThe sum of the array is %d", sum);
Chúng ta đã biết thế nào là mảng một chiều Điều này có nghĩa là các mảng chỉ
có một chỉ số Các mảng có thể có nhiều hơn một chiều Các mảng đa chiều giúp dễ
dàng trình bày các đối tượng đa chiều, chẳng hạn một đồ thị với các dòng và cột hay tọa độ màn hình của máy tính Các mảng đa chiều được khai báo giống như các mảng một chiều, ngoại trừ có thêm một cặp dấu ngoặc vuông [] trong trường hợp mảng hai chiều Một mảng ba chiều sẽ cần ba cặp dấu ngoặc vuông, Một cách tổng quát, một mảng đa chiều có thể được biểu diễn như sau:
Trang 17storage_class data_type ary[exp1][exp2] [expN];
Ở đó, ary là một mảng có lớp là storage_class, kiểu dữ liệu là data_type, và
exp1, exp2, , expN là các biểu thức nguyên dương xác định số phần tử của mảng
được kết hợp với mỗi chiều
Dạng đơn giản nhất và thường được sử dụng nhất của các mảng đa chiều là
mảng hai chiều Một mảng hai chiều có thể xem như là một mảng của hai „mảng một
chiều‟ Một mảng hai chiều đặc trưng như bảng lịch trình của máy bay, xe lửa Để xác định thông tin, ta sẽ chỉ định dòng và cột cần thiết, và thông tin được đọc ra từ vị trí (dòng và cột) được tìm thấy Tương tự như vậy, một mảng hai chiều là một khung lưới chứa các dòng và cột trong đó mỗi phần tử được xác định duy nhất bằng toạ độ
dòng và cột của nó Một mảng hai chiều tmp có kiểu int với 2 dòng và 3 cột có thể
được khai báo như sau:
int tmp[2][3];
Mảng này sẽ chứa 2 x 3 (6) phần tử, và chúng có thể được biểu diễn như sau:
Dòng
Cột
Ở đó e1 – e6 biểu diễn cho các phần tử của mảng Cả dòng và cột được đánh số
từ 0 Phần tử e6 được xác định bằng dòng 1 và cột 2 Truy xuất đến phần tử này như sau:
int row, col;
for(row = 0; row < 2; row++)
Trang 18for(row = 0; row < 2; row++)
- Xuất phần tử min, max
5 Viết chương trình nhập ma trận vuông n phần tử (n được nhập từ bàn phím)
- Xuất 2 đường chéo của ma trận
Trang 19Con trỏ là biến chứa địa chỉ của một biến khác Con trỏ được sử dụng rất nhiều trong C, một phần là do chúng đôi khi là cách duy nhất để biểu diễn tính toán, và phần nữa do chúng thường làm cho chương trình ngắn gọn và có hiệu quả hơn các cách khác
Bài này sẽ trình bày cách khai báo và sử dụng được con trỏ, các phép toán trên con trỏ trong lập trình, phân biệt các kiểu con trỏ, cách sử dụng con trỏ trong lập trình
Trang 20Mục tiêu
- Khai báo và sử dụng được con trỏ
- Vận dụng được các phép toán trên con trỏ trong lập trình
- Phân biệt được các kiểu con trỏ
Con trỏ có thể được sử dụng trong một số trường hợp sau:
Để trả về nhiều hơn một giá trị từ một hàm
Thuận tiện hơn trong việc truyền các mảng và chuỗi từ một hàm đến một hàm khác
Sử dụng con trỏ để làm việc với các phần tử của mảng thay vì truy xuất trực tiếp vào các phần tử này
Để cấp phát bộ nhớ động và truy xuất vào vùng nhớ được cấp phát này (dynamic memory allocation)
II CON TRỎ VÀ ĐỊA CHỈ
Vì con trỏ chứa địa chỉ của đối tượng nên nó có thể xâm nhập vào đối tượng gián tiếp qua con trỏ Giả sử x là một biến kiểu int, và giả sử px là con trỏ được tạo ra theo một cách nào đó
Phép toán một ngôi & sẽ cho địa chỉ của đối tượng, nên câu lệnh:
px=&x;
sẽ gán địa chỉ của biến x cho trỏ px, và px bây giờ được gọi là " trỏ tới biến x "
Phép toán một ngôi * coi là toán hạng của nó là đại chỉ cần xét và thâm nhập tới địa chỉ đó để lấy ra nội dung Nếu biến y có kiểu int thì thì lệnh:
Trang 21y=x;
Các khai báo cho các biến con trỏ có dạng:
tên kiểu *tên con trỏ
Ví dụ: Như trong ví dụ trên, ta khai báo con trỏ px kiểu int:
int *px;
Trong khai báo trên ta đã ngụ ý nói rằng đó là một cách tượng trưng, rằng tổ hợp
*px có kiểu int, tức là nếu px xuất hiện trong ngữ cảnh *px thì nó cũng tương đương với biến có kiểu int
Con trỏ có thể xuất hiện trong các biểu thức Chẳng hạn, nếu px trỏ tới số nguyên x thì *px có thể xuất hiện trong bất kỳ ngữ cảnh nào mà x có thể xuất hiện