Kỹ thuật lập trì nh
85
CHƯƠNG 4 CON TRỏ (POINTER)
I. ĐịNH NGHĩA
Con trỏ là một kiể u dữ liệ u dùng để chứa địa chỉ . Biế n con trỏ là một biế n
chứa địa chỉ của một thực thể nào đó, thực thể đó là biến hoặc là hàm.
Con trỏ thường đ ược dùng để :
- Trả về nhiề u trị từ hà m qua cơ chế truyề n theo tham số theo địa chỉ trong
hà m (tham số hì nh thức biế n).
- Tạ o cá c cấ u trúc dữ liệ u phức tạ p như danh sá ch liê n kế t và câ y nhị phâ n.
- Truyề n mả ng và chuỗi giữa cá c hà m khá thuậ n lợi.
I.1. Khai báo
: Khai bá o biế n pi là con trỏ trỏ đế n một số nguyê n.
int *pi;
Lúc nà y, pi chiế m 2 bytes chứa địa chỉ của số nguyê n mà nó đang chỉ
đế n, đồng thời trì nh biê n dịch của C cũng biế t pi đang chỉ đế n một số nguyê n
(do khai bá o). Để đ ưa một giá trị nguyê n và o vùng nhớ mà pi đang trỏ đế n, ta
dùng lệ nh: *pi = 1;
Ví dụ
:
void main()
{ int x=4, y=10;
int *px, *py ; // px, py là cá c biế n con trỏ
px = &x ; // đ ưa địa chỉ của x,y và o px và py
py = &y;
*px = *px + *py; // tă ng giá trị của vùng nhớ mà px đang trỏ tới
// thê m y , tương đ ương với x = x+y
}
Minh họa chương trì nh trê n trong bộ nhớ
:
Biế n int x=4, y=10;
int *px, *py;
px=&x;
py=&y;
*px = *px + *py;
x 950 4 4 14
951
y 952 10 10 10
953
px 950 950
py 952 952
Kỹ thuật lập trì nh
86
Hì nh 7.1. Cơ chế truy xuấ t giá trị qua biế n con trỏ.
Tổng quá t
: Kiểu *biến;
I.2. Truyề n địa chỉ cho hàm
: Trong 1 số trường hợp ta muốn gởi địa chỉ của
1 biế n x cho hà m. Nhờ và o cơ chế truyề n theo địa chỉ nà y mà hà m có thể trả về
nhiề u giá trị cho chương trì nh gọi.
Ví dụ
: Hà m hoá n đổi giá trị của 2 biế n x, y
void hoandoi (int *a, int *b)
{ int tam;
tam = *a;
*a = *b;
*b = tam;
}
void main()
{ int x,y;
printf ("x, y = ");
scanf ("%d %d", &x, &y);
giaohoan(&x, &y); // Truyề n địa chỉ của 2 biế n x,y cho hà m hoandoi
}
II Các phép toán trên biến con trỏ:
II.1. Toán tử địa chỉ &:
Nế u x là biế n thông thường, &x sẽ là địa chỉ của biế n x
Ví dụ
: float x, *pf;
x = 50;
pf = x; // sai vì pf là biế n con trỏ nê n ta viế t pf = & x;
x = pf; // sai ; ta viế t x = *pf; { lấ y nội dung của pf }
II.2. Toán tử nội dung * :
Nế u p là pointer thì *p là nội dung của nó.
Ví dụ
: int x,y, *p;
x = 50;
p = &x; // p chứa địa chỉ của vùng nhớ x
y = *p; // y= *p = 50 vì p chứa địa chỉ của vùng nhớ x
Ví dụ
: a =2;
p = & a;
b = (*p) + + + 3; // b =5, *p = 3, a= 3.
( vì p trỏ tới địa chỉ a nê n *p tă ng thì a tă ng)
Tóm lại
: *x là biế n mà x giữ địa chỉ
&x là địa chỉ của x nế u x là biế n thông thường
Kỹ thuật lập trì nh
87
II.3. Phép cộng trừ biế n con trỏ với một số nguyê n:
Nế u p là biế n pointer thì p+n là địa chỉ của một biế n mới cá ch nó n biế n
theo chiề u tă ng, còn p-n thì ngược lạ i.
Chú ý
:
- Phép cộng con trỏ với một số nguyê n chỉ đ ược á p dụng trê n một d y biế n
cùng kiể u
- Không đ ược cộng 2 pointer với nhau
- Không đ ược nhâ n, chia, lấ y dư biế n con trỏ với bấ t kỳ số nà o
Ví dụ
: Giả sử ta có mả ng nums[]= {10,20,30,40,50}. Việ c tham khả o tới
nums[i] thực chấ t là dùng dạ ng ký hiệ u con trỏ, vì khi biê n dịch, trì nh biê n dịch
sẽ chuyể n đổi ký hiệ u mả ng thà nh ký hiệ u con trỏ.
void main()
{ static int nums [] = {10,20,30,40,50};
for (int i =0; i<5; i++)
printf (%d\n, *(nums + i));
}
Lưu ý
: *(nums+i) tương đ ương với nums[i]
II.4. Phép gán và phép so sánh
:
- Phép gán: cá c biế n con trỏ có thể gá n cho nhau với điề u kiệ n phả i cùng
kiể u
Ví dụ
: int *p1, *p2;
*p1 = 10;
p2 = p1; // lúc nà y *p2 = 10;
- Phép so sánh: ta có thể so sá nh 2 biế n con trỏ xem có cùng địa chỉ hay
không, đ ương nhiê n 2 biế n con trỏ đó phả i cùng kiể u với nhau.
II.5. Sự chuyể n kiể u:
Cú phá p
: ( Kiể u) *tê nbiế n
Ví dụ
: int *p1, num ;
float *p2;
num =5;
p1 = #
*p2 = (float ) *p1; // * p2 = 5.0
Ví dụ
: int num, *p, n;
char c;
p = #
Kỹ thuật lập trì nh
88
*p = 97; // num =97
n = *p; // n=97
c = (char) *p; // c = a
Chú ý
: Địa chỉ của một biế n đ ược xem như một con trỏ hằ ng, do đó nó
không đ ược phép gá n, tă ng hoặ c giả m.
Ví dụ
: int num, *p, n;
p = & num;
p ++; // đúng
( & num) ++; // sai
con trỏ hằ ng
II.6. Khai báo một con trỏ hằng và con trỏ chỉ đế n đối tượng hằng:
a. Con trỏ hằng:
Kiể u * const p = giá trị;
b. Con trỏ chỉ đến đối tượng hằng:
Kiể u const *p = giá trị hằ ng;
hoặ c Const kiể u *p = giá trị hằ ng;
Ví dụ
: char *const p2 = ABCD
const char *p1= ABCD
p2 + + ; // sai
p1 + + ; // đúng; *p1= B ; p1 = "BCD"
III. Sự tương quan giữa con trỏ và mảng
Ví dụ
: Ta có mả ng A như sau:
int A[10] , *p;
thì A = &A[0]
Nế u p = A thì để truy xuấ t tới phầ n tử thứ i của mả ng A, ta có cá c cá ch sau:
A[i]
*(A + i)
*( p + i)
& A[i]
(A + i)
(p +i )
Ví dụ
: Nhậ p mả ng A:
int A[10] , *p, i;
p = A;
for (i = 0; i< 9; i++)
scanf (%d, p+i );
Xuấ t mả ng A
:
for (i = 0; i< 9;i++)
printf (%d, *(p+i));
Kü thuËt lËp tr× nh
89
VÝ dô: S¾ p xÕ p m¶ ng b» ng c¸ ch tham kh¶ o con trá.
const n =10 ;
int a[n], *p;
void main()
{ int j,temp;
clrscr();
p=a;
printf("\Nhap day so A :\n");
for (int i=0; i<n; i++)
{ printf("A[%d] = ",i+1);
scanf("%d",p+i);
}
// Sap xep mang A theo giai thuat Bubble Sort
for ( i=1; i<n; i++)
for (j=n-1; j>=i; j--)
if (*(p+j-1) > *(p+j))
{ temp = *(p+j);
*(p+j) = *(p+j-1);
*(p+j-1) = temp;
}
printf("\n Mang A sau khi sap xep :\n");
for ( i=0; i<n; i++)
printf("%8d",*(p+i));
}
* §èi víi m¶ ng 2 chiÒ u
:
NÕ u ta khai b¸ o : KiÓ u a [10] [20] , *p; th× m¶ ng a cã d¹ ng:
a 0 1 2 3 ..... 18 19
0
1
2
3
a[i]
.
9
NhËn xÐt:
a = &a[0][0] = &a[0]
a[i] = &a[i][0]