
Bài 13 Con trỏ
M c tiêu:ụ
K t thúc bài h c này, b n có th :ế ọ ạ ể
Hi u con tr là gì, và con tr đ c s d ng đâuể ỏ ỏ ượ ử ụ ở
Bi t cách s d ng bi n con tr và các toán t con trế ử ụ ế ỏ ử ỏ
Gán giá tr cho con trị ỏ
Hi u các phép toán s h c con trể ố ọ ỏ
Hi u các phép toán so sánh con trể ỏ
Bi t cách truy n tham s con tr cho hàmế ề ố ỏ
Hi u cách s d ng con tr k t h p v i m ng m t chi uể ử ụ ỏ ế ợ ớ ả ộ ề
Hi u cách s d ng con tr k t h p v i m ng đa chi uể ử ụ ỏ ế ợ ớ ả ề
Hi u cách c p phát b nh đ c th c hi n nh th nàoể ấ ộ ớ ượ ự ệ ư ế
Gi i thi uớ ệ
Con tr cung c p m t cách th c truy xu t bi n mà không tham chi u tr c ti p đ n bi n. Nó cungỏ ấ ộ ứ ấ ế ế ự ế ế ế
c p cách th c s d ng đ a ch . Bài này s đ c p đ n các khái ni m v con tr và cách s d ngấ ứ ử ụ ị ỉ ẽ ề ậ ế ệ ề ỏ ử ụ
chúng trong C.
13.1 Con tr là gì?ỏ
M t ộcon tr ỏ là m t bi nộ ế , nó ch a đ a ch vùng nh c a m t bi n khác, ch không l u tr giá trứ ị ỉ ớ ủ ộ ế ứ ư ữ ị
c a bi n đó. N u m t bi n ch a đ a ch c a m t bi n khác, thì bi n này đ c g i là ủ ế ế ộ ế ứ ị ỉ ủ ộ ế ế ượ ọ con tr ỏđ nế
bi n th hai kia. M t con tr cung c p ph ng th c gián ti p đ truy xu t giá tr c a các ph n tế ứ ộ ỏ ấ ươ ứ ế ể ấ ị ủ ầ ử
d li u. Xét hai bi n var1 và var2, var1 có giá tr 500 và đ c l u t i đ a ch 1000 trong b nh .ữ ệ ế ị ượ ư ạ ị ỉ ộ ớ
N u var2 đ c khai báo nh là m t con tr t i bi n var1, s bi u di n s nh sau:ế ượ ư ộ ỏ ớ ế ự ể ễ ẽ ư
V tríịGiá trịTên
B nhộ ớ l u trư ữ bi nế
1000 500 var1
1001
1002
.
.
1108 1000 var2
đây, var2 ch a giá tr 1000, đó là đ a ch c a bi n var1.Ở ứ ị ị ỉ ủ ế
Các con tr có th tr đ n các bi n c a các ki u d li u c s nh ỏ ể ỏ ế ế ủ ể ữ ệ ơ ở ư int, char, hay double ho c dặ ữ
li u có c u trúc nh ệ ấ ư m ngả.
Con trỏ181

13.1.2 T i sao con tr đ c dùng?ạ ỏ ượ
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)
13.2 Các bi n con trế ỏ
N u m t bi n đ c s d ng nh m t con tr , nó ph i đ c khai báo tr c. Câu l nh khai báo conế ộ ế ượ ử ụ ư ộ ỏ ả ượ ướ ệ
tr bao g m m t ki u d li u c b n, m t d u *, và m t tên bi n. Cú pháp t ng quát đ khai báoỏ ồ ộ ể ữ ệ ơ ả ộ ấ ộ ế ổ ể
m t bi n con tr nh sau:ộ ế ỏ ư
type *name;
đó Ởtype là m t ki u d li u h p l b t kỳ, và ộ ể ữ ệ ợ ệ ấ name là tên c a bi n con tr . Câu l nh khai báoủ ế ỏ ệ
trên nói v i trình biên d ch là ớ ị name đ c s d ng đ l u đ a ch c a m t bi n có ki u d li uượ ử ụ ể ư ị ỉ ủ ộ ế ể ữ ệ
type. Trong câu l nh khai báo, * xác đ nh r ng m t bi n con tr đang đ c khai báo.ệ ị ằ ộ ế ỏ ượ
Trong ví d c a ụ ủ var1 và var2 ỏ trên, vì var2 là m t con tr gi đ a ch c a bi n ộ ỏ ữ ị ỉ ủ ế var1 có ki u ểint,
nó s đ c khai báo nh sau:ẽ ượ ư
int *var2;
Bây gi , ờvar2 có th đ c s d ng trong m t ch ng trình đ tr c ti p truy xu t giá tr c a ể ượ ử ụ ộ ươ ể ự ế ấ ị ủ var1.
Nh r ng, ớ ằ var2 không ph i có ki u d li u ả ể ữ ệ int nh ng nó là m t con tr tr đ n m t bi n có ki uư ộ ỏ ỏ ế ộ ế ể
d li u int.ữ ệ
Ki u d li u c s c a con tr xác đ nh ki u c a bi n mà con tr tr đ n. V m t k thu t, m tể ữ ệ ơ ở ủ ỏ ị ể ủ ế ỏ ỏ ế ề ặ ỹ ậ ộ
con tr có ki u b t kỳ có th tr đ n b t kỳ v trí nào trong b nh . Tuy nhiên, t t c các phép toánỏ ể ấ ể ỏ ế ấ ị ộ ớ ấ ả
s h c trên con tr đ u có liên quan đ n ki u c s c a nó, vì v y khai báo ki u d li u c a conố ọ ỏ ề ế ể ơ ở ủ ậ ể ữ ệ ủ
tr m t cách rõ ràng là đi u r t quan tr ng.ỏ ộ ề ấ ọ
13.3 Các toán t con trử ỏ
Có hai toán t đ c bi t đ c dùng v i con tr : ử ặ ệ ượ ớ ỏ * và &. Toán t ử& là m t toán t m t ngôi và nóộ ử ộ
tr v đ a ch c a toán h ngả ề ị ỉ ủ ạ . Ví d ,ụ
var2 = &var1;
l y đ a ch vùng nh c a bi n var1 gán cho var2. Đ a ch này là v trí ô nh bên trong máy tính c aấ ị ỉ ớ ủ ế ị ỉ ị ớ ủ
bi n var1 và nó không làm gì v i giá tr c a var1. Toán t ế ớ ị ủ ử & có th hi u là tr v “đ a ch c a”. Vìể ể ả ề ị ỉ ủ
v y, phép gán trên có nghĩa là “var2 nh n đ a ch c a var1”. Tr l i, giá tr c a var1 là 500 và nóậ ậ ị ỉ ủ ở ạ ị ủ
dùng vùng nh ớ1000 đ l u giá tr này. Sau phép gán trên, ể ư ị var2 s có giá tr ẽ ị 1000.
Toán t th hai, toán t ử ứ ử *, đ c dùng v i con tr là ph n b xung c a toán t ượ ớ ỏ ầ ổ ủ ử &. Nó là m t toán tộ ử
m t ngôi và tr v giá tr ch a trong vùng nh đ c tr b i giá tr c a bi n con tr .ộ ả ề ị ứ ớ ượ ỏ ở ị ủ ế ỏ
Xem ví d tr c, đó ụ ướ ở var1 có giá tr 500 và đ c l u trong vùng nh 1000, sau câu l nh ị ượ ư ớ ệ
182 L p trình c b n Cậ ơ ả

var2 = &var1;
var2 ch a giá tr 1000, và sau l nh gánứ ị ệ
temp = *var2;
temp s ch a 500 không ph i là 1000. Toán t ẽ ứ ả ử * có th đ c hi u là “t i đ a ch ”.ể ượ ể ạ ị ỉ
C hai toán t * và ả ử & có đ u tiên cao h n t t c các toán t toán h c ngo i tr toán t l y giá trộ ư ơ ấ ả ử ọ ạ ừ ử ấ ị
âm. Chúng có cùng đ u tiên v i toán t l y giá tr âm (-).ộ ư ớ ử ấ ị
Ch ng trình d i đây in ra giá tr c a m t bi n ki u s nguyên, đ a ch c a nó đ c l u trong m tươ ướ ị ủ ộ ế ể ố ị ỉ ủ ượ ư ộ
bi n con tr , và ch ng trình cũng in ra đ a ch c a bi n con tr .ế ỏ ươ ị ỉ ủ ế ỏ
#include <stdio.h>
void main()
{
int var = 500, *ptr_var;
/* var is declared as an integer and ptr_var as a pointer
pointing to an integer */
ptr_var = &var; /*stores address of var in ptr_var*/
/* Prints value of variable (var) and address where var is
stored */
printf(“The value %d is stored at address %u:”, var, &var);
/* Prints value stored in ptr variable (ptr_var) and address
where ptr_var is stored */
printf(“\nThe value %u is stored at address: %u”,
ptr_var, &ptr_var);
/* Prints value of variable (var) and address where
var is stored, using pointer to variable */
printf(“\nThe value %d is stored at address:%u”, *ptr_var,
ptr_var);
}
K t qu c a ví d trên đ c hi n th ra nh sau:ế ả ủ ụ ượ ể ị ư
The value 500 is stored at address: 65500
The value 65500 is stored at address: 65502
The value 500 is stored at address: 65500
Trong ví d trên, ụptr_var ch a đ a ch 65500, là đ a ch vùng nh l u tr giá tr c a ứ ị ỉ ị ỉ ớ ư ữ ị ủ var. N i dung ôộ
nh 65500 này có th l y đ c b ng cách s d ng toán t ớ ể ấ ượ ằ ử ụ ử *, nh *ptr_var. Lúc này *ptr_var t ngư ươ
ng v i giá tr 500, là giá tr c a ứ ớ ị ị ủ var. B i vì ởptr_var cũng là m t bi n, nên đ a ch c a nó có thộ ế ị ỉ ủ ể
đ c in ra b ng toán t ượ ằ ử &. Trong ví d trên, ptr_var đ c l u t i đ a ch 65502. Mã quy cách %uụ ượ ư ạ ị ỉ
ch đ nh cách in giá tr các tham s theo ki u s nguyên không d u (unsigned int).ỉ ị ị ố ể ố ấ
Con trỏ183

Nh l i là, m t bi n ki u s nguyên chi m 2 bytes b nh . Vì v y, giá tr c a var đ c l u tr t iớ ạ ộ ế ể ố ế ộ ớ ậ ị ủ ượ ư ữ ạ
đ a ch 65500 và trình biên d ch c p phát ô nh k ti p 65502 cho ptr_var. T ng t , m t s th pị ỉ ị ấ ớ ế ế ươ ự ộ ố ậ
phân ki u float yêu c u 4 bytes và ki u double yêu c u 8 bytes. Các bi n con tr l u tr m t giá trể ầ ể ầ ế ỏ ư ữ ộ ị
nguyên. V i h u h t các ch ng trình s d ng con tr , ki u con tr có th xem nh m t giá tr 16-ớ ầ ế ươ ử ụ ỏ ể ỏ ể ư ộ ị
bit – chi m 2 bytes b nh .ế ộ ớ
Chú ý r ng hai câu l nh sau cho ra cùng m t k t qu .ằ ệ ộ ế ả
printf(“The value is %d”, var);
printf(“The value is %d”, *(&var));
Gán giá tr cho con trị ỏ
Các giá tr có th đ c gán cho bi n con tr thông qua toán t ị ể ượ ế ỏ ử &. Câu l nh gán s là:ệ ẽ
ptr_var = &var;
Lúc này đ a ch c a ị ỉ ủ var đ c l u trong bi n ượ ư ế ptr_var. Cũng có th gán giá tr cho con tr thông quaể ị ỏ
m t bi n con tr khác tr đ n m t ph n t d li u có cùng ki u.ộ ế ỏ ỏ ế ộ ầ ử ữ ệ ể
ptr_var = &var;
ptr_var2 = ptr_var;
Giá tr NULL cũng có th đ c gán đ n m t con tr b ng s 0 nh sau:ị ể ượ ế ộ ỏ ằ ố ư
ptr_var = 0;
Các bi n cũng có th đ c gán giá tr thông qua con tr c a chúng.ế ể ượ ị ỏ ủ
*ptr_var = 10;
s gán ẽ10 cho bi n ếvar n u ếptr_var tr đ n ỏ ế var.
Nói chung, các bi u th c có ch a con tr cũng theo cùng qui lu t nh các bi u th c khác trong C.ể ứ ứ ỏ ậ ư ể ứ
Đi u quan tr ng c n chú ý ph i gán giá tr cho bi n con tr tr c khi s d ng chúng; n u khôngề ọ ầ ả ị ế ỏ ướ ử ụ ế
chúng có th tr đ n m t giá tr không xác đ nh nào đó.ể ỏ ế ộ ị ị
Phép toán s h c con trố ọ ỏ
Ch phép c ng và tr là các toán t có th th c hi n trên các con tr . Ví d sau minh h a đi u này:ỉ ộ ừ ử ể ự ệ ỏ ụ ọ ề
int var, *ptr_var;
ptr_var = &var;
var = 500;
Trong ví d trên, chúng ta gi s r ng ụ ả ử ằ var đ c l u t i đ a ch ượ ư ạ ị ỉ 1000. Sau đó, giá tr ị1000 s đ cẽ ượ
l u vào ưptr_var. Vì ki u s nguyên chi m 2 bytes, nên sau bi u th c:ể ố ế ể ứ
ptr_var++ ;
ptr_var s ch a ẽ ứ 1002 mà KHÔNG ph i là ả1001. Đi u này có nghĩa là ptr_var bây gi tr đ n m tề ờ ỏ ế ộ
s nguyên đ c l u t i đ a ch 1002. M i khi ptr_var đ c tăng lên, nó s tr đ n s nguyên kố ượ ư ạ ị ỉ ỗ ượ ẽ ỏ ế ố ế
ti p và b i vì các s nguyên là 2 bytes, ptr_var s đ c tăng tr là 2. Đi u này cũng t ng t v iế ở ố ẽ ượ ị ề ươ ự ớ
phép toán gi m tr .ả ị
184 L p trình c b n Cậ ơ ả

Đây là m t vài ví d .ộ ụ
++ptr_var or ptr_var++ Tr đ n ỏ ế s nguyên ốk ti p đ ng sau varế ế ứ
--ptr_var or ptr_var-- Tr đ n ỏ ế s nguyênố đ ng tr c varứ ướ
ptr_var + i Tr đ n s nguyên th i sau varỏ ế ố ứ
ptr_var - i Tr đ n s nguyên th i tr c varỏ ế ố ứ ướ
++*ptr_var or (*ptr_var)++ S tăng tr ẽ ị var b i 1ở
*ptr_var++ S tác đ ng đ n giá tr c a s nguyên k ti p sau varẽ ộ ế ị ủ ố ế ế
M i khi m t con tr đ c tăng giá tr , nó s tr đ n ô nh c a ph n t k ti p. M i khi nó đ cỗ ộ ỏ ượ ị ẽ ỏ ế ớ ủ ầ ử ế ế ỗ ượ
gi m giá tr , nó s tr đ n v trí c a ph n t đ ng tr c nó. V i nh ng con tr tr t i các ký t , nóả ị ẽ ỏ ế ị ủ ầ ử ứ ướ ớ ữ ỏ ỏ ớ ự
xu t hi n bình th ng, b i vì m i ký t chi m 1 byte. Tuy nhiên, t t c nh ng con tr khác s tăngấ ệ ườ ở ỗ ự ế ấ ả ữ ỏ ẽ
ho c gi m tr tuỳ thu c vào đ dài ki u d li u mà chúng tr t i. ặ ả ị ộ ộ ể ữ ệ ỏ ớ
Nh đã th y trong các ví d trên, ngoài các toán t tăng tr và gi m tr , các s nguyên cũng có thư ấ ụ ử ị ả ị ố ể
đ c c ng vào và tr ra v i con tr . Ngoài phép c ng và tr m t con tr v i m t s nguyên, khôngượ ộ ừ ớ ỏ ộ ừ ộ ỏ ớ ộ ố
có m t phép toán nào khác có th th c hi n đ c trên các con tr . Nói rõ h n, các con tr khôngộ ể ự ệ ượ ỏ ơ ỏ
th đ c nhân ho c chia. Cũng nh ki u float và double không th đ c c ng ho c tr v i con tr .ể ượ ặ ư ể ể ượ ộ ặ ừ ớ ỏ
So sánh con tr .ỏ
Hai con tr có th đ c so sánh trong m t bi u th c quan h . Tuy nhiên, đi u này ch có th n uỏ ể ượ ộ ể ứ ệ ề ỉ ể ế
c hai bi n này đ u tr đ n các bi n có cùng ki u d li u. ả ế ề ỏ ế ế ể ữ ệ ptr_a và ptr_b là hai bi n con tr trế ỏ ỏ
đ n các ph n t d li u ế ầ ử ữ ệ a và b. Trong tr ng h p này, các phép so sánh sau đây là có th th cườ ợ ể ự
hi n:ệ
ptr_a < ptr_b Tr v giá tr true n u ả ề ị ế a đ c l u tr v trí tr c ượ ư ữ ở ị ướ b
ptr_a > ptr_b Tr v giá tr true n u ả ề ị ế a đ c l u tr v trí sau ượ ư ữ ở ị b
ptr_a <= ptr_b Tr v giá tr true n u ả ề ị ế a đ c l u tr v trí tr c ượ ư ữ ở ị ướ b ho c ptr_a và ptr_b trặ ỏ
đ n cùng m t v tríế ộ ị
ptr_a >= ptr_b Tr v giá tr true n u ả ề ị ế a đ c l u tr v trí sau ượ ư ữ ở ị b ho c ptr_a và ptr_b trặ ỏ
đ n cùng m t v tríế ộ ị
ptr_a == ptr_b Tr v giá tr true n u c hai con tr ptr_a và ptr_b tr đ n cùng m t ph nả ề ị ế ả ỏ ỏ ế ộ ầ
t d li u.ử ữ ệ
ptr_a != ptr_b Tr v giá tr true n u c hai con tr ptr_a và ptr_b tr đ n các ph n t dả ề ị ế ả ỏ ỏ ế ầ ử ữ
li u khác nhau nh ng có cùng ki u d li u.ệ ư ể ữ ệ
ptr_a == NULL Tr v giá tr true n u ptr_a đ c gán giá tr NULL (0)ả ề ị ế ượ ị
T ng t , n u ươ ự ế ptr_begin và ptr_end tr đ n các ph n t c a cùng m t m ng thì,ỏ ế ầ ử ủ ộ ả
ptr_end - ptr_begin
s tr v s bytes cách bi t gi hai v trí mà chúng tr đ n.ẽ ả ề ố ệ ữ ị ỏ ế
13.4 Con tr và m ng m t chi uỏ ả ộ ề
Tên c a m t m ng th t ra là m t con tr tr đ n ph n t đ u tiên c a m ng đó. Vì v y, n u ủ ộ ả ậ ộ ỏ ỏ ế ầ ử ầ ủ ả ậ ế ary là
m t m ng m t chi u, thì đ a ch c a ph n t đ u tiên trong m ng có th đ c bi u di n làộ ả ộ ề ị ỉ ủ ầ ử ầ ả ể ượ ể ễ
&ary[0] ho c đ n gi n ch là ặ ơ ả ỉ ary. T ng t , đ a ch c a ph n t m ng th hai có th đ c vi tươ ự ị ỉ ủ ầ ử ả ứ ể ượ ế
nh ư&ary[1] ho c ặary+1,... T ng quát, đ a ch c a ph n t m ng th (i + 1) có th đ c bi u di nổ ị ỉ ủ ầ ử ả ứ ể ượ ể ễ
là &ary[i] hay (ary+i). Nh v y, đ a ch c a m t ph n t m ng b t kỳ có th đ c bi u di n theoư ậ ị ỉ ủ ộ ầ ử ả ấ ể ượ ể ễ
hai cách:
Con trỏ185

