C / C ++ - Chương IV: Con trỏ và số học địa chỉ

4.1. Địa chỉ, phép toán &

4.2. Con trỏ

4.3. Các phép toán với con trỏ

4.4. Cấp phát và thu hồi bộ nhớ động

4.5. Con trỏ và mảng, chuỗi

4.6. Mảng con trỏ

pdf 22 trang dienloan 17260
Bạn đang xem 20 trang mẫu của tài liệu "C / C ++ - Chương IV: Con trỏ và số học địa chỉ", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

Tóm tắt nội dung tài liệu: C / C ++ - Chương IV: Con trỏ và số học địa chỉ

C / C ++ - Chương IV: Con trỏ và số học địa chỉ
LOGO
Chương IV
Con trỏ và số học địa chỉ
COMPANY LOGO
www.themegallery.com
Nội dung chính
Trường ĐH GTVT TP.HCM - Bài giảng : Kỹ thuật lập trình 2
4.1. Địa chỉ, phép toán &
4.2. Con trỏ
4.3. Các phép toán với con trỏ
4.4. Cấp phát và thu hồi bộ nhớ động
4.5. Con trỏ và mảng, chuỗi
4.6. Mảng con trỏ
COMPANY LOGO
www.themegallery.com
4.1 Địa chỉ, phép toán &
Trường ĐH GTVT TP.HCM - Bài giảng : Kỹ thuật lập trình 3
 Địa chỉ của một biến là địa chỉ byte nhớ đầu tiên của biến đó.
 C++ cung cấp một toán tử một ngôi & để lấy địa chỉ của các
biến (ngoại trừ biến mảng và xâu kí tự). Nếu x là một biến thì
&x là địa chỉ của x.
 Đối với biến kiểu mảng, thì tên mảng chính là địa chỉ của
mảng, do đó không cần dùng đến toán tử &.
200 201 500 501 502 503 650 651   658
1 2 4 3 2 1 H E L L O \0
x y s
Biến x chiếm 2 byte nhớ, có địa chỉ là 200, biến y có địa chỉ là
500 và chiếm 4 byte nhớ. Xâu s chiếm 9 byte nhớ tại địa chỉ
650. Các byte nhớ của một biến là liền nhau.
COMPANY LOGO
www.themegallery.com
4.1 Địa chỉ, phép toán &
Trường ĐH GTVT TP.HCM - Bài giảng : Kỹ thuật lập trình 4
Ghi nhớ:
int x; // khai báo biến nguyên x
long y; // khai báo biến nguyên dài y
cout << &x << &y; // in địa chỉ các biến x, y
char s[9]; // khai báo mảng kí tự s
cout << s; // in địa chỉ mảng s
cout << &s[0]; // in địa chỉ mảng s (tức địa chỉ s[0])
cout << &s[2]; // in địa chỉ kí tự s[2]
Các phép toán liên quan đến địa chỉ được gọi là số học địa chỉ.
Các thao tác được phép trên địa chỉ vẫn phải thông qua các biến
trung gian chứa địa chỉ, được gọi là biến con trỏ.
COMPANY LOGO
www.themegallery.com
4.2 Con trỏ
Trường ĐH GTVT TP.HCM - Bài giảng : Kỹ thuật lập trình 5
 Con trỏ là một biến chứa địa chỉ của biến khác. Nếu p là con
trỏ chứa địa chỉ của biến x ta gọi p trỏ tới x và x được trỏ bởi
p. Thông qua con trỏ ta có thể làm việc được với nội dung của
những ô nhớ mà p trỏ đến.
 Để con trỏ p trỏ tới x ta phải gán địa chỉ của x cho p.
 Để làm việc với địa chỉ của các biến cần phải thông qua các
biến con trỏ trỏ đến biến đó.
COMPANY LOGO
www.themegallery.com
4.2 Con trỏ
Trường ĐH GTVT TP.HCM - Bài giảng : Kỹ thuật lập trình 6
 Khai báo biến con trỏ
Ví dụ 1:
int *p ; // khai báo biến con trỏ p trỏ đến kiểu số nguyên.
float *q, *r ; // khai báo hai con trỏ thực q và r.
 Sử dụng con trỏ, phép toán *
 Để con trỏ p trỏ đến biến x ta viết:
• p=&x //Nếu x không phải là mảng
• p=x hoặc p=&x[0] //Nếu x là mảng
 Phép toán * cho phép lấy nội dung nơi p trỏ đến, ví dụ để
gán nội dung nơi p trỏ đến cho biến f ta viết f = *p.
 & và * là 2 phép toán ngược nhau( nếu p = &x thì x = *p).
 ;
COMPANY LOGO
www.themegallery.com
4.2 Con trỏ
Trường ĐH GTVT TP.HCM - Bài giảng : Kỹ thuật lập trình 7
Ví dụ 2:
int i, j ; // khai báo 2 biến nguyên i, j
int *p, *q ; // khai báo 2 con trỏ nguyên p, q
p = &i; // cho p trỏ tới i
q = &j; // cho q trỏ tới j
cout << &i ; // hỏi địa chỉ biến i
cout << q ; // hỏi địa chỉ biến j (thông qua q)
i = 2; // gán i bằng 2
*q = 5; // gán j bằng 5 (thông qua q)
i++ ; cout << i ; // tăng i và hỏi i, i = 3
(*q)++ ; cout << j ; // tăng j (thông qua q) và hỏi j, j = 6
(*p) = (*q) * 2 + 1; // gán lại i (thông qua p)
cout << i ; // 13
COMPANY LOGO
www.themegallery.com
4.3 Các phép toán với con trỏ
Trường ĐH GTVT TP.HCM - Bài giảng : Kỹ thuật lập trình 8
A. Phép toán gán :
o Gán con trỏ với địa chỉ một biến: p = &x ;
o Gán con trỏ với con trỏ khác: p = q ; (sau phép toán gán
này p, q chứa cùng một địa chỉ, cùng trỏ đến một nơi).
Ví dụ:
int i = 10 ; // khai báo và khởi tạo biến i = 10
int *p, *q, *r ; // khai báo 3 con trỏ nguyên p, q, r
p = q = r = &i ; // cùng trỏ tới i
*p = q**q + 2**r + 1; // i = 10*10 + 2*10 + 1
cout << i ; // 121
COMPANY LOGO
www.themegallery.com
4.3 Các phép toán với con trỏ
Trường ĐH GTVT TP.HCM - Bài giảng : Kỹ thuật lập trình 9
B. Phép toán tăng giảm địa chỉ:
o p ± n: Con trỏ trỏ đến thành phần thứ n sau (trước) p.
(Một đơn vị tăng giảm của con trỏ bằng kích thước của
biến được trỏ).
o p++, p--, ++p, --p: tương tự p+1 và p-1, có chú ý đến
tăng (giảm) trước, sau.
Ví dụ 1:
Giả sử p là con trỏ nguyên (2 byte) đang trỏ đến địa chỉ
200 thì p+1 là con trỏ trỏ đến địa chỉ 202.
Ví dụ 2:
int a[] = { 1, 2, 3, 4, 5, 6, 7 }, *p, *q;
p = a; cout << *p ; //trỏ p đến mảng a, *p = a[0]= 1
p += 5; cout << *p ; // *p = a[5] = 6 ;
q = p - 4 ; cout << *q ; // q = a[1] = 2 ;
COMPANY LOGO
www.themegallery.com
4.3 Các phép toán với con trỏ
Trường ĐH GTVT TP.HCM - Bài giảng : Kỹ thuật lập trình 10
C. Hiệu của hai cong trỏ:
Phép toán này chỉ thực hiện được khi p và q là 2 con trỏ
cùng trỏ đến các phần tử của một dãy dữ liệu nào đó trong bộ
nhớ (ví dụ cùng trỏ đến 1 mảng dữ liệu).
Khi đó hiệu p - q là số thành phần giữa p và q (chú ý p - q
không phải là hiệu của 2 địa chỉ mà là số thành phần giữa p và
q).
Ví dụ: Giả sử p và q là 2 con trỏ nguyên, p có địa chỉ 200 và q có
địa chỉ 208. Khi đó p - q = - 4 và q - p = 4 (4 là số thành phần
nguyên từ địa chỉ 200 đến 208).
COMPANY LOGO
www.themegallery.com
4.3 Các phép toán với con trỏ
Trường ĐH GTVT TP.HCM - Bài giảng : Kỹ thuật lập trình 11
D. Phép toán so sánh:
Thông thường các phép so sánh chỉ áp dụng cho hai con
trỏ trỏ đến phần tử của cùng một mảng dữ liệu nào đó.
Ví dụ :
float a[100], *p, *q ;
p = a ; // p trỏ đến mảng a(tức p trỏ đến a[0])
q = &a[3] ; // q trỏ đến phần tử thứ 3 (a[3]) của mảng
cout << (p < q) ; // 1
cout << (p + 3 == q) ; // 1
cout q - 1) ; // 0
cout = q - 2) ; // 0
for (p=a ; p < a+100; p++)
cout << *p ; // in toàn bộ mảng a
COMPANY LOGO
www.themegallery.com
4.4 Cấp phát và thu hồi bộ nhớ động
Trường ĐH GTVT TP.HCM - Bài giảng : Kỹ thuật lập trình 12
A. Cấp phát bộ nhớ động với toán tử new:
o p = new ; // cấp phát 1 phần tử
o p = new [n] ; // cấp phát n phần tử
Khi gặp toán tử new, chương trình sẽ tìm trong bộ nhớ
một lượng ô nhớ còn rỗi và liên tục với số lượng đủ theo yêu
cầu và cho p trỏ đến địa chỉ (byte đầu tiên) của vùng nhớ này.
Nếu không có vùng nhớ với số lượng như vậy thì việc cấp phát
là thất bại và p = NULL (NULL là một địa chỉ rỗng, không
xác định).
COMPANY LOGO
www.themegallery.com
4.4 Cấp phát và thu hồi bộ nhớ động
Trường ĐH GTVT TP.HCM - Bài giảng : Kỹ thuật lập trình 13
B. Thu hồi bộ nhớ động với toán tử delete:
o Để giải phóng bộ nhớ đã cấp phát cho một biến (khi
không cần sử dụng nữa) ta sử dụng câu lệnh delete.
delete p ; // p là con trỏ được sử dụng trong new
o Và để giải phóng toàn bộ mảng được cấp pháp thông qua
con trỏ p ta dùng câu lệnh:
delete[] p ; // p là con trỏ trỏ đến mảng
o Dùng hàm free:
free(p); //P là biến con trỏ
COMPANY LOGO
www.themegallery.com
Ví dụ : Sắp xếp dãy số
Trường ĐH GTVT TP.HCM - Bài giảng : Kỹ thuật lập trình 14
#include
using namespace std;
int main()
{
int *dau, *p, *q, n, tam; // dau sẽ là số đầu tiên của dãy
cout << "Cho biet so luong phan tu cua day: ";
cin >> n ;
dau = new int[n] ; // Cấp cho dau n phần tử số nguyên
for (p = dau; p<dau+n; p++) // nhập dãy
{
cout > *p ;
}
for (p=dau; p<dau+n-1; p++) // Sắp xếp dãy
for (q=p+1; q<dau+n; q++)
if (*q < *p)
{ tam = *p; *p = *q; *q = tam; }
for (p=dau; p<dau+n; p++) cout << *p <<"\t"; // Xuất dãy
delete dau; // Thu hồi bộ nhớ
}
COMPANY LOGO
www.themegallery.com
4.5 Con trỏ và mảng, chuỗi
Trường ĐH GTVT TP.HCM - Bài giảng : Kỹ thuật lập trình 15
A. Con trỏ và mảng 1 chiều : Việc cho con trỏ trỏ đến mảng
cũng tương tự trỏ đến các biến khác, tức gán địa chỉ của
mảng (chính là tên mảng) cho con trỏ. Chú ý rằng địa chỉ của
mảng cũng là địa chỉ của thành phần thứ 0 nên a+i sẽ là địa
chỉ thành phần thứ i của mảng a.
Ví dụ: In toàn bộ mảng thông qua con trỏ.
Cho : int a[5] = {1, 2, 3, 4, 5}, *p, i;
Cách 1:
p = a;
for (i=0; i<5; i++) cout << *(p+i) <<"\t";
// p không thay đổi
Cách 2:
for (p=a; p<=a+4; p++) cout << *p <<"\t";
// thay đổi p
COMPANY LOGO
www.themegallery.com
4.5 Con trỏ và mảng, chuỗi
Trường ĐH GTVT TP.HCM - Bài giảng : Kỹ thuật lập trình 16
B. Con trỏ và mảng 2 chiều : Ví dụ sau đây cho phép nhập và
in một mảng 2 chiều m*n (m dòng, n cột) thông qua con trỏ
p. Nhập liên tiếp m*n số vào mảng và in thành ma trận m
dòng, n cột.
float a[2][3], *p;
int i, j;
p = (float*) a;
for (i=0; i> *(p+i);
// Nhập dãy 6 phần tử.
for (i=0; i<2; i++) // In dãy dạng ma trận
{
for (j=0; j<3; j++) cout << *(p+i*3+j)<<" ";
cout << endl;
}
COMPANY LOGO
www.themegallery.com
4.5 Con trỏ và mảng, chuỗi
Trường ĐH GTVT TP.HCM - Bài giảng : Kỹ thuật lập trình 17
C. Con trỏ và chuỗi:
Một con trỏ kí tự có thể xem như một biến xâu kí tự,
trong đó xâu chính là tất cả các kí tự kể từ byte con trỏ trỏ đến
cho đến byte '\0' gặp đầu tiên.
Các hàm trên xâu vẫn được sử dụng như khi ta khai báo
nó dưới dạng mảng kí tự.
Ngoài ra khác với mảng kí tự, ta được phép sử dụng phép
gán cho 2 xâu dưới dạng con trỏ.
Khi khai báo xâu dạng con trỏ nó vẫn chưa có bộ nhớ cụ
thể, vì vậy thông thường kèm theo khai báo ta cần phải xin cấp
phát bộ nhớ cho xâu với độ dài cần thiết.
COMPANY LOGO
www.themegallery.com
Ví dụ
Trường ĐH GTVT TP.HCM - Bài giảng : Kỹ thuật lập trình 18
#include
#include
using namespace std;
int main()
{
char *s="Ky Thuat Lap Trinh", *t;
t = new char[33]; //Cấp phát bộ nhớ động cho t
strncpy(t, s, 8); //Copy nội dung 8 kí tự đầu của s sang t
cout<<t;
}
COMPANY LOGO
www.themegallery.com
4.6 Mảng con trỏ
Trường ĐH GTVT TP.HCM - Bài giảng : Kỹ thuật lập trình 19
Mảng con trỏ là mảng trong đó các phần tử của nó là một 
con trỏ trỏ đến một mảng nào đó. Nói cách khác một mảng con 
trỏ cho phép quản lý nhiều mảng dữ liệu cùng kiểu. 
Cách khai báo:
 *a[size];
Ví dụ: 
int *a[10];
/* khai báo một mảng chứa 10 con trỏ. Mỗi con trỏ a[i] 
chứa địa chỉ của một mảng nguyên nào đó. */
COMPANY LOGO
www.themegallery.com
Ví dụ
Trường ĐH GTVT TP.HCM - Bài giảng : Kỹ thuật lập trình 20
#include
using namespace std;
int main()
{
int a[4]={1,2,3,4}, b[4]={4,5,6}, c[4]={9,8,7,3}, i, j;
int *p[3]={a, b, c}; // mảng p là các con trỏ trỏ đến a, b, c
for(i=0; i<3; i++)
{ for(j=0; j<4; p[i]++, j++)
cout<<*p[i]<<" ";
cout<<endl;
}
}
COMPANY LOGO
www.themegallery.com
Bài Tập Chương 4
Trường ĐH GTVT TP.HCM - Bài giảng : Kỹ thuật lập trình 21
Bài 1. Hãy khai báo biến kí tự ch và con trỏ kiểu kí tự pc trỏ vào 
biến ch. Viết ra các cách gán giá trị ‘A’ cho biến ch. 
Bài 2. Sử dụng con trỏ nhập một dãy số nguyên gồm n phần tử.
A. Xuất dãy ra màn hình theo chiều ngược lại
B. Xác định phần tử có giá trị lớn nhất và vị trí của nó
C. Sắp xếp dãy tăng dần
D. Sắp xếp mảng như sau: bên trái là các phần tử âm giảm dần, ở 
giữa là số không ( nếu có), bên phải là các số dương tăng dần
Bài 3. Cho xâu kí tự (dạng con trỏ) s. 
A. Hãy copy từ s sang xâu t một đoạn bắt đầu tại vị trí m với độ 
dài n.
B. Đổi các kí tự (nếu là chữ cái) đầu tiên sau các khoảng trắng 
của t sang chữ in hoa.
LOGO
www.themegallery.com 

File đính kèm:

  • pdfc_c_chuong_iv_con_tro_va_so_hoc_dia_chi.pdf