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 không tham chi u tr c ti p đ n bi 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 cách s d ng ế
chúng trong C.
13.1 Con tr là gì?
M t con tr m t bi 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 ế ế ế ế ế ượ 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 var2, var1 giá tr 500 đ 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á trTê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 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 tr181
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 truy xu t tr c ti p vào các ế
ph n t này
Đ c p phát b nh đ ng 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 *, m t tên bi n. pháp t ng quát đ khai báo ơ ế
m t bi n con tr nh sau: ế ư
type *name;
đó type m t ki u d li u h p l b t kỳ, name 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 name đ c s d ng đ l u đ a ch c a m t bi n 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 d c a var1 var2 trên, var2 m t con tr gi đ a ch c a bi n ế var1 ki u int,
nó s đ c khai báo nh sau: ượ ư
int *var2;
Bây gi , var2 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 ki u d li u int nh ng m t con tr tr đ n m t bi n 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 con tr tr đ n. V m t k thu t, m t ơ ế ế
con tr 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 liên quan đ n ki u c s c a nó, 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
hai toán t đ c bi t đ c dùng v i con tr : ượ * &. Toán t & m t toán t m t ngôi
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 y v trí ô nh n trong máy tính c a ế
bi n var1 không làm v i giá tr c a var1. Toán t ế & th hi u là tr v “đ a ch c a”. Vì
v y, phép gán trên nghĩa “var2 nh n đ a ch c a var1”. Tr l i, giá tr c a var1 500
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à &đ 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, giá tr c a var. B i ptr_var cũng m t bi n, nên đ a ch c a th ế
đ c in ra b ng toán t ượ &. Trong d trên, ptr_var đ c l u t i đ a ch 65502. 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 tr183
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 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 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 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 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 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 KHÔNG ph i 1001. Đi u này nghĩa 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, s tr đ n s nguyên k ượ ư ượ ế ế
ti p b i các s nguyên 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 , s tr đ n ô nh c a ph n t k ti p. M i khi đ 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 d trên, ngoài các toán t tăng tr gi m tr , các s nguyên cũng 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ượ
m t phép toán nào khác th th c hi n đ c trên các con tr . Nói 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 th đ c so sánh trong m t bi u th c quan h . Tuy nhiên, đi u này ch th n u ượ ế
c hai bi n này đ u tr đ n các bi n cùng ki u d li u. ế ế ế ptr_a ptr_b hai bi n con tr trế
đ n các ph n t d li u ế a b. Trong tr ng h p này, các phép so sánh sau đây 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 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 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 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_beginptr_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
m t m ng m t chi u, thì đ a ch c a ph n t đ u tiên trong m ng th đ c bi u di n là ượ
&ary[0] ho c đ n gi n ch ơ ary. T ng t , đ a ch c a ph n t m ng th hai 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 ượ
&ary[i] hay (ary+i). Nh v y, đ a ch c a m t ph n t m ng b t kỳ th đ c bi u di n theoư ượ
hai cách:
Con tr185