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 ề ỏ ế ợ ử ụ ể ả ớ

c th c hi n nh th nào  Hi u cách c p phát b nh đ ấ ớ ượ ể ộ ư ế ự ệ

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ì? ỏ

ế , nó ch a đ a ch vùng nh c a m t bi n khác, ch không l u tr giá tr ộ ứ ị ữ ế ộ ế ớ ủ ế ỉ ỉ ủ ứ ị ế ộ ứ ượ ng th c gián ti p đ truy xu t giá tr c a các ph n t ế ứ ươ ứ ị ư con tr ỏ đ nế c g i là ọ ầ ử ị ủ ớ i đ a ch 1000 trong b nh . ộ i bi n var1, M t ộ con tr ỏ là m t bi n 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 đ ộ ế ủ bi n th hai kia. M t con tr cung c p ph ể ấ ế ấ ỏ ộ ế d li u. Xét hai bi n var1 và var2, var1 có giá tr 500 và đ c l u t ượ ư ạ ị ữ ệ ế c khai báo nh là m t con tr t N u var2 đ ự ể ế ỏ ớ ị ế ượ ư ộ ỉ ễ ẽ ư ơ s bi u di n s nh sau:

Giá trị l u trư ữ 500 Tên bi nế var1

V trí ị B nhộ ớ 1000 1001 1002 . . 1108 1000 var2

đây, var2 ch a giá tr 1000, đó là đ a ch c a bi n var1. Ở ỉ ủ ứ ế ị ị

181

Con trỏ

ể ỏ ế ế ủ ữ ệ ơ ở ể ư int, char, hay double ho c dặ ữ Các con tr có th tr đ n các bi n c a các ki u d li u c s nh ỏ li u có c u trúc nh ấ ư m ngả . ệ

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: ợ

m t hàm ơ ể ả ề ệ ả ế ộ c a m ng thay vì truy xu t tr c ti p vào các ầ ử ủ ỏ ể ệ ớ m t hàm đ n m t hàm khác ỗ ừ ộ ả ấ ự ế ầ ử c c p phát này (dynamic memory ớ ộ ấ ộ ớ ượ ấ  Đ tr v nhi u h n m t giá tr t ị ừ ộ ộ ề  Thu n ti n h n trong vi c truy n các m ng và chu i t ậ ề ệ ơ  S d ng con tr đ làm vi c v i các ph n t ử ụ này ph n t  Đ c p phát b nh đ ng và truy xu t vào vùng nh đ ể ấ allocation)

13.2 Các bi n con tr ế ỏ

ế ượ ử ụ ướ ệ c khai báo tr ế ư ộ ơ ả ỏ ộ ấ ữ ệ ể ồ ổ c s d ng nh m t con tr , nó ph i đ N u m t bi n đ 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;

ủ ể ệ ỏ ể ế ớ name là tên c a bi n con tr . Câu l nh khai báo ữ ệ h p lợ ệ b t kỳ, và đó Ở type là m t ki u d li u ấ ế ộ c s d ng đ l u đ a ch c a m t bi n có ki u d li u name đ trên nói v i trình biên d ch là ữ ệ ượ ử ụ ộ ỉ ủ ị c khai báo. type. Trong câu l nh khai báo, * xác đ nh r ng m t bi n con tr đang đ ộ ằ ị ể ư ế ị ỏ ượ ệ

ộ ỏ ữ ị đ a ch c a bi n ỉ ủ ế var1 có ki u ể int, Trong ví d c a nó s đ ụ ủ var1 và var2 ỏ trên, vì var2 là m t con tr gi c khai báo nh sau: ẽ ượ ư

int *var2;

ng trình đ tr c ti p truy xu t giá tr c a , ờ var2 có th đ ế ấ ộ var2 không ph i có ki u d li u c s d ng trong m t ch ể ượ ử ụ ả ị ủ var1. ể ữ ệ int nh ng nó là m t con tr tr đ n m t bi n có ki u ế ể ự ộ ỏ ỏ ế ươ ư ể ộ Bây gi Nh r ng, ớ ằ 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 bi m t ngôi và nó c dùng v i con tr : ớ ỏ * và &. Toán t ử & là m t toán t ộ ử ộ Có hai toán t t đ ử ặ ệ ượ 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 ấ ỉ ế ử & có th hi u là tr v “đ a ch c a”. Vì bi n var1 và nó không làm gì v i giá tr c a var1. Toán t ế i, giá tr c a var1 là 500 và nó v y, phép gán trên có nghĩa là “var2 nh n đ a ch c a var1”. Tr l ị ủ ậ ị 1000. dùng vùng nh ớ 1000 đ l u giá tr này. Sau phép gán trên, ị ở ạ var2 s có giá tr ẽ ể ư

, toán t c dùng v i con tr là ph n c a toán t ử ứ ử *, đ ỏ ử &, toán t m t ngôi và tr v giá tr ch a trong vùng nh đ Toán t m t toán t ộ th hai ử ộ ượ ả ề ớ ị ứ ầ bùb xung ổ ớ ượ ử *. Nó là c tr b i giá tr c a bi n con tr . ỏ ị ủ ủ ỏ ở ế

182

L p trình c b n C

ơ ả

Xem ví d tr c, đó var1 có giá tr 500 và đ ụ ướ ở ị ượ ư c l u trong vùng nh 1000, sau câu l nh ớ ệ

var2 = &var1;

var12 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 hi i đ a ch ”. ẽ ứ ả ử * có th đ ể ượ ểều là “t ạ ị ỉ

t c các toán t * và toán h c ngo i tr toán t l y giá tr ả ộ ư ử ử ạ ừ ọ ử ấ ị C hai toán t âm. Chúng có cùng đ u tiên v i toán t & có đ u tiên cao h n t ớ ộ ư ơ ấ ả l y giá tr âm (-). ị ử ấ

ỉ ủ ị ủ ị ượ ư ộ c l u trong m t Ch ướ ươ bi n con tr , và 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ó đ ươ ộ ng trình cũng in ra đ a ch c a bi n con tr . ỏ ị ể ố ế ế ỉ ủ

#include

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); }

c hi n th ra nh sau: M t ví d v k t qu th c thi ch ng trình nh ả ủ ụ ượ ư ể ị ụ ề ế ả ự ộ ươ ư K t qu c a ví d trên đ ế 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

183

Con trỏ

ụ ữ ộ ỉ ỉ c b ng cách s d ng toán t ớ ư ư ằ ng ng v i ể ấ ị ở ị ứ ị ượ ớ giá tr 500, là giá tr c a ị ủ var. N i dung ô trình ử *, nh *ptr_var. Lúc này *ptr_var ptr_var cũng là m t bi n, nên đ a ch c a nó ỉ ủ ế i đ a ch 65502. Mã quy cách ỉ c in ra b ng toán t ằ Trong ví d trên, nh 65500 này có th l y đ ớ bàyt có th đ %u ch đ nh cách in giá tr các tham s theo ki u s nguyên không d u (unsigned int). ptr_var ch a đ a ch 65500, là đ a ch vùng nh l u tr giá tr c a ị ử ụ ị ủ var. B i vì ử &. Trong ví d trên, ptr_var đ ụ ể ố ộ c l u t ượ ư ạ ị ấ ươ ứ ể ượ ị ố ỉ ị

ộ ế ế ậ ớ ớ ạ ỉ ể ố ị ượ ư ự ươ ấ 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 đ ng t ỏ ư ữ ộ ể ể ế ầ ư ộ ử ụ ươ ể ể ế ỏ ị Nh l c l u tr t ữ ạ i ộ ị ủ , m t s th p đ a ch 65500 và trình biên d ch c p phát ô nh k ti p 65502 cho ptr_var. T ộ ố ậ ớ ế ế ị 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 ị ầ ng trình s d ng con tr , ki u con tr có th xem nh m t giá tr 16- nguyên. V i h u h t các ch ỏ ớ ầ 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 gán cho bi n con tr thông qua toán t ể ượ ế ỏ ử &. Câu l nh gán s là: ệ ẽ Các giá tr có th đ ị ptr_var = &var;

c l u trong bi n ượ ư ế ptr_var. Cũng có th gán giá tr cho con tr thông qua ể ỏ ị d li u có cùng ki u. ỉ ủ var đ Lúc này đ a ch c a ị m t bi n con tr khác tr đ n m t ph n t ỏ ỏ ế ế ộ ộ ầ ử ữ ệ ể

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. ứ ứ c khi s d ng chúng; n u không Đi u quan tr ng c n chú ý ph i gán giá tr cho bi n con tr tr ả 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;

i đ a ch c l u t ượ ư ạ ị ả ử ằ ụ ỉ 1000. Sau đó, giá tr ị 1000 s đ ẽ ượ c Trong ví d trên, chúng ta gi l u vào ể ố ư s r ng var đ ptr_var. Vì ki u s nguyên chi m 2 bytes, nên sau bi u th c: ế ứ ể

ptr_var++ ;

184

L p trình c b n C

ơ ả

1001. Đi u này có nghĩa là ptr_var bây gi ề ả ờ ỏ ế i đ a ch 1002. M i khi ptr_var đ c tăng lên, nó s tr đ n s nguyên k ptr_var s ch a s nguyên đ ố ẽ ứ 1002 mà KHÔNG ph i là ỗ c l u t ượ ư ạ ị ỉ ượ ẽ ỏ ế ố ộ tr đ n m t ế

c tăng tr là 2. Đi u này cũng t ng t ế ố ẽ ượ ề ị ươ ự ớ v i ti p và b i vì các s nguyên là 2 bytes, ptr_var s đ ở phép toán gi m tr . ị ả

Đây là m t vài ví d . ụ ộ

c var

c var k ti p đ ng sau var ế ế ứ đ ng tr ứ ướ ứ ứ ướ

++ptr_var or ptr_var++ --ptr_var or ptr_var-- ptr_var + i ptr_var - i ++*ptr_var or (*ptr_var)++ *ptr_var++ Tr đ n ỏ ế s nguyên ố Tr đ n ỏ ế s nguyên ố Tr đ n s nguyên th i sau var ỏ ế ố Tr đ n s nguyên th i tr ỏ ế ố S tăng tr ẽ S tác đ ng đ n giá tr c a s nguyên k ti p sau var ị ủ ố ẽ ị var b i 1ở ế ế ế ộ

ỗ ị c nó. V i nh ng con tr tr t ớ ủ ớ giá tr , nó s tr đ n ô nh c a ph n t ủ ỗ ở ượ c k ti p. M i khi nó đ ầ ử ế ế ỗ i các ký t , nó ữ ự ỏ ỏ ớ t c nh ng con tr khác s tăng ẽ ỏ ấ ả ữ ẽ ỏ ế đ ng tr ầ ử ứ ướ chi m 1 byte. Tuy nhiên, t ế ự i. M i khi m t con tr đ c tăng ỏ ượ ộ gi mả giá tr , nó s tr đ n v trí c a ph n t ẽ ỏ ế ị ị ng, b i vì m i ký t xu t hi n bình th ườ ệ ho c gi m tr tuỳ thu c vào đ dài ki u d li u mà chúng tr t ộ ộ ả ể ữ ệ ỏ ớ ấ ặ ị

ấ ụ ả ố ị ị ừ ộ ộ ố ừ ớ ượ ệ ỏ c c ng ho c tr ư ểều float và double không th đ ặ ặ ể tăng tr và gi m tr , các s nguyên cũng có th Nh đã th y trong các ví d trên, ngoài các toán t ử ư 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 trên các con tr . Nói rõ h n, các con tr không có m t phép toán nào khác có th th c hi n đ ỏ ơ ể ự ộ v i con c nhân ho c chia. Cũng nh ki th đ ừ ớ ể ượ ộ ể ượ tr .ỏ

So sánh con tr .ỏ

ứ ề ể ộ ỉ ữ ệ ptr_a và ptr_b là hai bi n con tr tr ế ế 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 ể ế ệ ể ượ ỏ ỏ ề ỏ ế ể ự ng h p này, các phép so sánh sau đây là có th th c d li u ầ ử ữ ệ a và b. Trong tr ể ợ ườ Hai con tr có th đ ỏ c hai bi n này đ u tr đ n các bi n có cùng ki u d li u. ế ả đ n các ph n t ế hi n:ệ

c ướ b b c c l u tr c l u tr c l u tr v trí tr v trí sau v trí tr ptr_a < ptr_b ptr_a > ptr_b ptr_a <= ptr_b ữ ở ị ữ ở ị ữ ở ị ế a đ ế a đ ế a đ ượ ư ượ ư ượ ư ướ b ho c ptr_a và ptr_b tr ỏ ặ

ptr_a >= ptr_b b ho c ptr_a và ptr_b tr v trí sau c l u tr ượ ư ế a đ ữ ở ị ỏ ặ

ptr_a == ptr_b ị ị ị ộ ị ị ộ ị ị ỏ ế ế ả ỏ ộ

ptr_a != ptr_b d ầ ử ữ ỏ ế ả ị ư Tr v giá tr true n u ả ề Tr v giá tr true n u ả ề Tr v giá tr true n u ả ề đ n cùng m t v trí ế Tr v giá tr true n u ả ề đ n cùng m t v trí ế Tr v giá tr true n u c hai con tr ptr_a và ptr_b tr đ n cùng m t ph n ầ ả ề d li u. t ử ữ ệ Tr v giá tr true n u c hai con tr ptr_a và ptr_b tr đ n các ph n t ả ề ỏ ế li u khác nhau nh ng có cùng ki u d li u. ể ữ ệ ệ c gán giá tr NULL (0) ptr_a == NULL Tr v giá tr true n u ptr_a đ ị ả ề ượ ế ị

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

t gi hai v trí mà chúng tr đ n. s tr v s bytes cách bi ẽ ả ề ố ệ ữ ỏ ế ị

13.4 Con tr và m ng m t chi u ỏ ộ ề ả

185

Con trỏ

đ u tiên c a m ng đó. Vì v y, n u ộ ậ ả ủ ầ ử ầ ộ ả ộ ả ề ị ể ượ ỉ ủ ary. T ươ ặ ả ơ ỉ đ u tiên trong m ng có th đ ầ ử ả ứ m ng th (i + 1) có th đ Tên c a m t m ng th t ra là m t con tr tr đ n ph n t ỏ ỏ ế m t m ng m t chi u, thì đ a ch c a ph n t ầ ử ầ ộ , đ a ch c a ph n t &ary[0] ho c đ n gi n ch là ỉ ủ ự ị nh ư &ary[1] ho c ặ ary+1,... T ng quát, đ a ch c a ph n t ầ ử ả ỉ ủ ổ ng t ị ế ary là ủ ậ c bi u di n là ể ả ễ t m ng th hai có th đ ế c vi ể ượ ễ c bi u di n ể ứ ể ượ

m ng b t kỳ có th đ c bi u di n theo ỉ ủ ộ ị ầ ử ả ể ượ ấ ể ễ là &ary[i] hay (ary+i). Nh v y, đ a ch c a m t ph n t ư ậ hai cách:

c m t ph n t ầ ử ả ệ ộ c c ng vào tên c a m ng.  S d ng ký hi u & tr ướ  S d ng m t bi u th c trong đó ch s đ ứ m ng ỉ ố ượ ộ ử ụ ử ụ ể ộ ủ ả

i bi u di n s ỉ ể ư ượ ể ng tr ng cho m t đ a ch , trong khi ộ ị có th ứ (ary + i), ary t ả ế ữ ary là tên c a m t m ng mà các ph n t ộ ầ ử ủ ầ ử ả ố ữ ệ ể ả ỉ ộ ị ị ỉ ể ễ ố ể là c ả có kiểều s nguyên, ký c a m ng ph i có cùng ki u d li u). Vì v y, ậ trên không ch là m t phép c ng; nó th t ra là xác đ nh m t đ a ch , m t s xác đ nh c a ủ ậ ứ ứ (ary + i) là m t s trình bày cho m t đ a ch ch không ph i là m t bi u th c ộ ị ộ ố ả ỉ ứ ị ể ộ

ớ ượ ế ợ ớ ộ c, s l tr ố ượ ở ướ ế ư ể ị ể ả ầ ủ đ u tiên, đó là, m t giá tr ch s . Giá tr c a ng ô nh đ ủ m ng đ u tiên, đó là tên c a m ng (trong tr ộ ỉ ố ượ ị ầ ử ầ c dùng theo cách này. Ghi nh r ng trong bi u th c ớ ằ nguyên. H n th n a, ủ ơ t c các ph n t , s th p phân,… (dĩ nhiên, t t ấ ả ự ố ậ bi u th c ộ ộ ứ ở ể các ô nh . Bi u th c ộ ự ớ toán h c.ọ c k t h p v i m t m ng s tùy thu c vào ki u d li u ữ ệ Nh đã nói ộ ẽ ả ư i l p trình ch có th xác đ nh đ a ch c a m ng cũng nh là ki n trúc c a máy tính. Tuy nhiên, ng ỉ ị ườ ậ ả ỉ ủ ầ ử ary) và s các ph n t c a ph n t ng h p này là ườ ủ ố ơ ầ ử ả ộ độ c xem nh là m t ị ủ i đôi khi đ ti p sau ph n t ư ế d iờ khi đ ượ

ứ &ary[i] và (ary+i) bi u di n đ a ch ph n t ư ậ ộ ỉ ủ ị ể ể ễ ễ ị ủ ề ầ ử ứ i c a ủ ary, và nh v y m t cách th ầ ử ỉ ụ c s d ng trong b t kỳ ng d ng ary. C hai cách có th thay th cho nhau và đ ể ượ ử ụ ứ ấ ả i l p trình mong mu n. Các bi u th c ị ể logic là c ả ary[i] và *(ary + i) đ u bi u di n n i dung c a đ a ch đó, nghĩa là, giá tr c a ph n t ộ th ứ i trong m ng ả ế nào khi ng ườ ậ ố

Ch ng trình sau đây bi u di n m i quan h gi a các ph n t m ng và đ a ch c a chúng. ươ ệ ữ ầ ử ả ỉ ủ ể ễ ố ị

#include

void main() {

static int ary[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int i; for (i = 0; i < 10; i ++) { printf(“\n i = %d , ary[i] = %d , *(ary+i)= %d “, i, ary[i], *(ary + i));

printf(“&ary[i] = %X , ary + i = %X”, &ary[i], ary + i); /* %X gives unsigned hexadecimal */ } }

ng trình trên đ nh nghĩa m ng m t chi u ị ộ ả ầ ử ể ượ ố ể ể ị đ c gán giá tr t ỗ ị ươ ứ ng ng c a m i ph n t ầ ử ả ủ ằ ề ary, có 10 ph n t ặ for đ ng ng là 1, 2, ..10. Vòng l p ượ ỗ ị ủ ươ m ng. Chú ý r ng, giá tr c a m i ph n t ọ ự ươ c hi n th theo hai cách. K t qu m ng cũng đ ầ ử ki u s nguyên, các ph n t ỉ c dùng đ hi n th giá tr và đ a ch ị ị c xác đ nh theo hai cách ầ ử ượ ị ỉ ủ , đ a ch c a ng c a chúng. T ng t ự ị ủ trên như c a ch ng trình ả th c thi ủ ự ầ ử ả ng đ ế ươ ươ ằ ể ượ ị Ch ươ m ng đ ả t ươ ứ khác nhau, ary[i] và *(ary + i), nh m minh h a s t m i ph n t ỗ sau:

186

L p trình c b n C

ơ ả

ary[i]=1 ary[i]=2 ary[i]=3 ary[i]=4 ary[i]=5 ary[i]=6 ary[i]=7 ary[i]=8 *(ary+i)=1 *(ary+i)=2 *(ary+i)=3 *(ary+i)=4 *(ary+i)=5 *(ary+i)=6 *(ary+i)=7 *(ary+i)=8 &ary[i]=194 &ary[i]=196 &ary[i]=198 &ary[i]=19A &ary[i]=19C &ary[i]=19E &ary[i]=1A0 &ary[i]=1A2 ary+i = 194 ary+i = 196 ary+i = 198 ary+i = 19A ary+i = 19C ary+i = 19E ary+i = 1A0 ary+i = 1A2 i=0 i=1 i=2 i=3 i=4 i=5 i=6 i=7

*(ary+i)=9 i=8 i=9 &ary[i]=1A4 ary[i]=9 ary[i]=10 *(ary+i)=10 &ary[i]=1A6 ary+i = 1A4 ary+i = 1A6

ả ế ữ ary[i] - bi u di n giá tr c a ph n t ễ ầ ử ứ i trong th ị ủ ể K t qu này trình bày rõ ràng s khác nhau gi a m ngả , và &ary[i] - bi u di n đ a ch c a nó. ể ự ị ỉ ủ ễ

ộ ế ế ộ ậ ầ ử ả ị ự c gán đ n vùng nh mà đ a ch c a nó là ph n t ị ộ ớ ộ ị ư ary[i], v trái c a l nh gán có th đ ủ ệ c gán tr c ti p đ n m t ph n t ế ế ể ượ ầ ử ả ư ậ ể ượ ầ ử ả ầ ỏ ữ ộ ế ế ộ ị ệ ể ượ ỉ ế ủ ộ m ng. Đôi khi c n thi ả ặ ợ ỉ ể ộ ể ể ế ả ậ ứ ế ữ ệ ộ ệ ể ả ộ ơ ộ ỉ ủ c phép. Lý do là vì: ứ ị ắ ầ ở ượ ng h p nh v y, m t con tr ả ấ ổ ary là đ a ch c a m ng ỉ ủ ả đâu, ví d , b t đ u ụ ắ ầ ở ị ề ỉ ư ary++ là không đ ế c đ a ra, m ng s ượ ư c b t đ u ệ ố ắ ượ ế ị ả ỉ t là c vi Khi gán m t giá tr cho m t ph n t m ng nh ị ặ m ng ho c ary[i] ho c ặ *(ary + i). Vì v y, m t giá tr có th đ t ph i gán nó có th đ ả ế ỉ ủ ph i xu t hi n m t đ a ch đ n m t đ nh danh. Trong nh ng tr ệ ườ ấ ầ trong v trái c a câu l nh gán. Không th gán m t đ a ch tùy ý cho m t tên m ng ho c m t ph n ộ ộ ị c a m ng. Vì v y, các bi u th c nh t ư ary, (ary + i) và &ary[i] không th xu t hi n trong v trái ử ủ c a m t câu l nh gán. H n th n a, đ a ch c a m t m ng không th thay đ i m t cách tùy ý, vì ị ủ ary. Khi th các bi u th c nh ể ế ỉ m ng đ đ a ch c khai báo, b liên k t đã quy t đ nh m ng đ ượ ả ộ ả 1002. M t khi đ a ch này đ đó. Vi c c g ng tăng đ a ch này lên là đi u vô ộ ị ẽ ở nghĩa, gi ng nh khi nói ố ị ư

x = 5++;

B i vì h ng không th đ c tăng tr , trình biên d ch s đ a ra thông báo l i. ể ượ ằ ở ẽ ư ị ị ỗ

ợ ườ ộ h ng con tr ớ ằ ượ ằ ị ỏ. Nh r ng, (ary + 1) ờ ary đ n v trí (ary + 1), nó ch tr đ n v trí đó, trong khi ary++ c găng d i c xem nh là m t ư ỉ ỏ ế ố ị ng h p m ng ary, Trong tr ary cũng đ ả không di chuy n m ng ế ả ể ary sang 1 v trí. ị

c gán cho m t ph n t ỉ ủ ầ ử ả ộ m ng khác, m c dù giá tr c a m t ị ủ ặ ộ Đ a ch c a m t ph n t ộ ị m ng có th đ ph n t ầ ử ả ầ ử ể ượ không th đ ể ượ c gán cho m t ph n t ộ ầ ử khác thông qua con tr . ỏ

&ary[2] ary[2] = &ary[3]; = ary[3]; /* không cho phép*/ /* cho phép*/

ớ ạ ằ ữ ệ ơ ả ả ặ ế ả ạ ệ ề ố ả ề ị ầ ấ bi u di n đ a ch c a nó.Tuy nhiên, n u m t ph n t trong m ng đ ấ ỉ ộ ớ ủ ả ọ ế ữ ệ ế ự ể ầ ử ở ấ ỉ ủ ả ễ ượ ế ộ ị i r ng trong hàm scanf(), tên các tham bi n ki u d li u c b n ph i đ t sau d u (&), trong Nh l ể ớ ủ khi tên tham bi n m ng là ngo i l . Đi u này cũng d hi u. Vì scanf() đòi h i đ a ch b nh c a ỏ ị ễ ể & tr v đ a ch b nh c a bi n, do t ng bi n d li u trong danh sách tham s , trong khi toán t ỉ ộ ế ử ế ừ c yêu c u đ i v i tên m ng, b i vì đó tr c tên bi n ph i có d u &. Tuy nhiên d u & không đ ố ớ ướ ượ ấ c đ c, d u & tên m ng t ả ả c n ph i s d ng. ả ử ụ ầ

ử ầ ử ấ ầ ầ ố ố ớ ớ scanf(“%d”, *ary) /* scanf(“%d”, &ary[2]) /* đ i v i ph n t đ u tiên */ đ i v i ph n t b t kỳ */

13.4.1 Con tr và m ng nhi u chi u ả ỏ ề ề

c bi u di n d ề ề ộ ướ ạ ề ể ượ ự ề ề ở ể ệ ụ ỉ ố ộ ề ề ị ợ ủ ỏ ế ả ế ế ề ả ộ ộ i d ng con tr c a m ng m t chi u (tên M t m ng nhi u chi u cũng có th đ ả ỏ ủ ễ ề ả ộ c đi u này là b i vì m t m ng nhi u chi u là c a m ng) và m t đ d i (ch s ). Th c hi n đ ủ ả ộ ượ ộ ộ ờ ả c đ nh nghĩa nh là m t t p h p c a các m ng m t chi u.Ví d , m t m ng hai chi u có th đ ư ể ượ ộ ậ ộ ả m t con tr đ n m t nhóm các m ng m t chi u k ti p nhau. Cú pháp báo m ng hai chi u có th ể ộ ề ả vi ế t nh sau: ư

data_type (*ptr_var)[expr 2];

thay vì

187

Con trỏ

data_type array[expr 1][expr 2];

Khái ni m này có th đ c t ng quát hóa cho các m ng nhi u chi u, đó là, ể ượ ổ ệ ề ề ả

data_type (*ptr_var)[exp 2] .... [exp N];

thay vì

data_type array[exp 1][exp 2] ... [exp N];

ữ ệ ủ ể ả ỏ ptr_var là tên c a bi n con tr , ế ng xác đ nh ươ ả ị ị i đa các ph n t m ng đ ng t Trong các khai báo trên, data_type là ki u d li u c a m ng, array là tên m ng, và s l ố ố ượ ủ exp 1, exp 2, exp 3, ... exp N là các giá tr nguyên d ỗ c k t h p v i m i ch s . ỉ ố ớ ượ ế ợ ầ ử ả

ấ ả ấ ả ặ ặ ể ỏ c tên m ng trong cách khai báo theo ộ i cú pháp khai báo s khai báo m t ẽ Chú ý d u ngo c () bao quanh tên m ng và d u * phía tr d ng con tr . C p d u ngo c () là không th thi u, ng ạ ặ m ng c a các con tr ch không ph i m t con tr c a m t nhóm các m ng. ả ướ c l ượ ạ ộ ấ ỏ ứ ế ỏ ủ ủ ả ả ộ

Ví d , n u c khai báo nh sau: ụ ế ary là m t m ng hai chi u có 10 dòng và 20 c t, nó có th đ ể ượ ề ả ộ ộ ư

int (*ary)[20];

thay vì

int ary[10][20];

c đ nh nghĩa là m t con tr tr t ự ượ ị ộ ề ế ỗ ỏ ế i m t nhóm các m ng m t ộ ầ ử ầ đ u , (ary + 1) tr đ n dòng ng t ộ ki u s nguyên ầ ử ể ố ề ủ ủ ả ả ỏ ỏ ớ ả . Vì v y, ậ ary tr đ n ph n t ỏ ế ươ ự Trong s khai báo th nh t, ấ ary đ ứ chi u liên ti p nhau, m i m ng có 20 ph n t ả tiên c a m ng, đó là dòng đ u tiên (dòng 0) c a m ng hai chi u. T ầ th hai c a m ng hai chi u, ... ả ứ ủ ề

M t m ng th p phân ba chi u ề fl_ary có th đ ể ượ ậ ả ộ c khai báo nh : ư

float (*fl_ary)[20][30];

thay vì

float fl_ary[10][20][30];

ượ ị ư ề ậ ả c 20 x 30 liên ti p nhau. Vì v y, ế c đ nh nghĩa nh là m t nhóm các m ng th p phân hai chi u có ỏ ộ ỏ ế ả ầ ậ fl_ary tr đ n m ng 20 x 30 đ u tiên, (fl_ary + 1) tr Trong khai báo đ u, ầ fl_ary đ kích th ướ đ n m ng 20 x 30 th hai,... ả ế ứ

Trong m ng hai chi u t c truy xu t s d ng câu l nh: ề ary, ph n t ầ ử ạ ả i dòng 4 và c t 9 có th đ ộ ể ượ ấ ử ụ ệ

ary[3][8]; ho cặ *(*(ary + 3) + 8);

188

L p trình c b n C

ơ ả

ứ ượ ỏ ỏ ế ứ ộ ng đ ủ ộ ỏ ế ế tr đ n ph n t ầ ử ầ ộ ộ c c ng vào con tr . Vì v y, *(*(ary + 3) + 8) là m t con tr tr đ n ph n t ỏ ỏ ế ộ c dùng. Trong cách th hai, (ary + 3) là m t con tr tr đ n dòng ườ ng c a con tr này, *(ary + 3), tham chi u đ n toàn b dòng. Vì dòng 3 là đ u tiên trong dòng 3, sau đó 8 ầ ử ứ th 9) ỏ ỏ ế ế ng c a con tr này, *(*(ary + 3) + 8), tham chi u đ n tham chi u 8 (ph n t ầ ử ế ế ỏ ậ ủ ỏ ứ trong c t th 9 c a dòng th 4, đó là ary [3][8]. Cách th nh t là cách th ấ th 4. Vì v y, đ i t ứ ố ượ ậ m t m ng m t chi u, *(ary + 3) là m t con tr ộ ề ả đ ậ ượ ộ trong dòng th 4. Vì v y đ i t ố ượ đ n ph n t ủ ế ầ ử ứ ứ ộ

ự ề ả ứ ể ị ộ ể ử ứ ố ị ụ ạ Có nhi u cách th c đ đ nh nghĩa m ng, và có nhi u cách đ x lý các ph n t cách th c nào tùy thu c vào ng nghĩa m ng theo cách thông th ọ m ng. L a ch n ầ ử ả i dùng. Tuy nhiên, trong các ng d ng có các m ng d ng s , đ nh ả ng s d dàng h n. ề ứ ả ườ ườ ẽ ễ ơ

Con tr và chu i ỗ ỏ

ỉ ự ể ả ộ ố ộ ề ỗ ộ ỏ nhiên chu i cũng s có m i liên h m t thi strchr(). Hàm này nh n các tham s là m t chu i và m t ký t ệ ậ . M ng và con tr có m i liên h m t t v i con tr . Xem ỏ ố ự đ tìm ki m ký t ế ệ ậ ộ ế ớ ự ể ế ườ ẽ ố ậ ộ ỗ Chu i đ n gi n ch là m t m ng m t chi u có ki u ký t ả ỗ ơ ả thi t, và nh v y, m t cách t ự ư ậ ng h p hàm tr ợ đó trong m ng, nghĩa là, ả

ptr_str = strchr(strl, ‘a’);

c gán đ a ch c a ký t ‘a’ đ u tiên xu t hi n trong chu i ế ẽ ượ ự ệ ỏ ptr_str s đ ả ỗ ừ ị ế ỉ ủ ố 0 đ n cu i chu i, mà là đ a ch , t ỗ ỗ str. Đây ấ ị đ a ch b t đ u chu i đ n đ a ỉ ừ ị ỉ ắ ầ ỗ ế ầ ị bi n con tr không ph i là v trí trong chu i, t ị ch k t thúc c a chu i. ỉ ế ủ ỗ

ươ ng trình sau s d ng hàm strchr(), đây là ch ử ụ đ tìm ki m. Ch ng trình in ra đ a ch b t đ u c a chu i, đ a ch c a ký t ộ ườ ỗ ự ể ự ế ươ ỗ ự ứ ị ng trình cho phép ng ỉ ắ ầ ủ ị đ u tiên, 1 là v trí c a ký t ị ự ầ ỗ ộ i dùng nh p vào m t ậ , và ỉ ủ th hai,...). ự trong chu i (0 là v trí c a ký t ự ị ệ ố ữ ỉ ắ ầ ủ ị ủ ị ỉ ơ ủ ị ỉ Ch ươ chu i và m t ký t ỗ v ị trí t ng đ i c a ký t ươ ố ủ ng đ i này là hi u s gi a hai đ a ch , đ a ch b t đ u c a chu i và đ a ch n i mà ký t V trí t ố ươ ị c n tìm đ u tiên xu t hi n. ầ ầ ệ ấ

#include #include

void main () {

char a, str[81], *ptr; printf(“\nEnter a sentence:”); gets(str); printf(“\nEnter character to search for:”); a = getche(); ptr = strchr(str, a);

/* return pointer to char*/ printf(“\nString starts at address: %u”, str); printf(“\nFirst occurrence of the character is at address: %u”, ptr); printf(“\nPosition of first occurrence (starting from 0)is: %d”,

ptr-str); }

c hi n th ra nh sau: M t ví d v k t qu th c hi n ch ng trình nh ả ủ ụ ượ ư ể ị ụ ề ế ả ự ệ ộ ươ ư K t qu c a ví d trên đ ế sau:

Enter a sentence: We all live in a yellow submarine Enter character to search for: Y String starts at address: 65420. First occurrence of the character is at address: 65437. Position of first occurrence (starting from 0) is: 17

189

Con trỏ

c thi t đ t đ ch a đ a ch tr v t hàm strchr(), vì ế ệ ế ặ ể ứ ị ỉ ả ề ừ Trong câu l nh khai báo, bi n con tr v y đây là m t đ a ch c a m t ký t ậ ỏ ptr đ ượ ự (ptr có ki u ể char). ộ ị ỉ ủ ộ

Hàm strchr() không c n thi t ph i khai báo n u th vi n c khai báo. ầ ế ư ệ string.h đ ế ả ượ

13.5 C p phát b nh ộ ớ ấ

ờ ộ ể ế ế ủ ả ơ ả ủ ữ ộ ườ ị ả ế ỏ c dành s n t ư ả ộ ộ ẵ ạ ế ố ộ ượ ể ộ ộ ế ờ ư ề ả ớ ố ị ế ả ộ ộ ng đ ầ t là tên c a m t m ng th t ra là m t con tr tr t i ph n ỏ ỏ ớ ậ ng có th đ nh nghĩa ể ị c khai báo m t cách bình ộ ươ ng ự ỏ ử ụ c khai báo nh là m t bi n con tr . S d ng ượ c khi các ệ ướ c th c hi n b ng cách ằ ư ậ ả ả i th i đi m b t đ u th c thi ch ắ ầ ế ở ạ ự ễ ự ấ ộ ớ ượ ườ ớ Cho đ n th i đi m này thì chúng ta đã bi đ u tiên c a m ng. H n n a, ngoài cách đ nh nghĩa m t m ng thông th t ử ầ m t m ng nh là m t bi n con tr . Tuy nhiên, n u m t m ng đ ộ ng, k t qu là m t kh i b nh c đ nh đ th ượ ườ trình, trong khi đi u này không x y ra n u m ng đ ả m t bi n con tr đ bi u di n m t m ng đòi h i vi c gán m t vài ô nh kh i t o tr ộ ỏ ế c x lý. S c p phát b nh nh v y thông th m ng đ ph n t ệ ộ ầ ử ả s d ng hàm th vi n ử ụ ỏ ể ể ượ ử ư ệ malloc().

có th đ c khai báo nh sau: Xem ví d sau. M t m ng s nguyên m t chi u ả ề ary có 20 ph n t ầ ử ụ ộ ộ ố ể ượ ư

int *ary;

thay vì

int ary[20];

ẽ ộ ớ ộ ộ ượ c khai báo nh là m t con tr , s l đ ng gán m t kh i b nh khi nó đ ố ộ ẽ ượ ố ớ ủ ể ứ ư ượ ả ộ ế c khai báo nh là m t bi n ư ượ c khai ế ary đ c dành s n n u ẵ ể ượ c ng b nh có th đ ớ ộ ỏ ố ượ Tuy nhiên, ary s không đ c t ượ ự ộ con tr , trong khi m t kh i ô nh đ đ ch a 10 s nguyên s đ ỏ ố báo nh là m t m ng. N u ế ary đ ư ộ gán nh sau: ư

ary = malloc(20 *sizeof(int));

ng đ c (tính theo bytes) t c c a m t s ẽ ướ ươ ươ ớ Ở ượ ấ ng v i kích th ố ẽ ả ề ế ể ư ể ư ể ộ ử ụ ỉ ị ớ ượ ả ủ ứ ấ ỏ ị c yêu c u trong m t ch ng trình đ ự ấ c g i là ọ ị ả ề ươ ượ ượ ầ ấ ộ ố S dành m t kh i b nh có kích th ộ ướ ủ ớ ố ộ đây, m t kh i b nh cho 20 s nguyên đ ộ c c p phát. 20 con s gán v i 20 bytes (m t nguyên. ớ ố ớ ố ộ ộ c nhân v i ả , n u máy tính ớ sizeof(int), sizeof(int) s tr v k t qu 2 byte cho m t s nguyên) và đ ượ ộ ố ế m t s nguyên. N u m t máy tính s d ng 1 byte đ l u m t s nguyên, dùng 2 bytes đ l u tr ữ ộ ố ế ộ ố ử ụ đây. Tuy nhiên, s d ng nó s t o kh năng uy n chuy n cho mã hàm sizeof() không đòi h i ỏ ở ể ẽ ạ c c p phát. l nh. Hàm malloc() tr v m t con tr ch a đ a ch v trí b t đ u c a vùng nh đ ả ề ộ ệ ắ ầ N u không gian b nh yêu c u không có, malloc() tr v giá tr NULL. S c p phát b nh theo ớ ộ ầ ớ ộ ế cách này, nghĩa là, khi đ ớ C p phát b nh ộ ộ đ ngộ .

C p phát b nh ả ế ụ ộ ấ c khi ti p t c xa h n, chúng ta hãy th o lu n v khái niêm ng trình C ữ ướ ươ ứ ơ ể ư ồ ườ ụ ụ ồ ậ ộ ộ ố ế ự ư ố ị ế ế t tr ươ ế ờ ượ ả ộ thông qua c t ng s dung l ố c l u tr ể ượ ư ấ ụ ườ ậ ứ Tr ch pháp th nh t bao g m các bi n toàn c c và c c b – bao g m các m ng. Trong tr ả bi n toàn c c và bi n tĩnh, s l u tr là c đ nh su t th i gian th c thi ch ữ đòi h i ng i l p trình ph i bi ế ướ ổ ỏ Ph ng pháp th hai, thông tin có th đ ươ Trong ph c c p phát t ớ đ ngộ . M tộ ề ng có th l u tr các thông tin trong b nh c a máy tính theo hai cách chính. Ph ươ ớ ủ ng h p các ợ ng trình. Các bi n này ế ợ ng h p. t cho m i tr ỗ ườ c a Củ H th ng c p phát đ ng . ộ ấ t. do và khi c n thi ế ầ ự ự ng b nh c n thi ớ ầ ệ ố vùng nh còn t ớ ng pháp này, s l u tr thông tin đ ự ư ữ ượ ấ ươ ừ ữ

ng đ ượ vùng nh còn t do. Tham s cho c dùng nh t, nó cho phép th c hi n vi c c p phát t. malloc() là m t s nguyên xác đ nh s bytes c n thi Hàm malloc() là m t trong các hàm th ộ b nh t ớ ộ ườ ố ớ ừ ự ệ ấ ầ ấ ộ ố ệ ố ự ị ế

hai chi u ụ ự ả ề ch_ary có 10 dòng và 20 c t. S khai báo và c p phát b ộ ự ấ ộ ng h p này ph i nh sau: M t ví d khác, xét m ng ký t nh trong tr ả ộ ớ ườ ư ợ

190

L p trình c b n C

ơ ả

char (*ch_ary)[20];

ch_ary = (char*)malloc(10*20*sizeof(char));

trên, malloc() tr v m t con tr tr đ n ki u r ng (void). Tuy nhiên, vì ể ỗ t. Trong câu l nh trên, (char*) đ i ki u tr v ư ộ ở ỏ ể ỏ ỏ ế ầ ế ể ệ ổ ch_ary là ả ề ể Nh đã nói m t con tr ki u char, s chuy n đ i ki u là c n thi ự c a ủ malloc() thành m t con tr tr đ n ki u char. ả ề ộ ể ổ ỏ ỏ ế ể ộ

ế ự ở ạ ả ả ị ả ượ c Tuy nhiên, n u s khai báo c a m ng ph i ch a phép gán các giá tr kh i t o thì m ng ph i đ ứ ủ ng, không th dùng m t bi n con tr : khai báo theo cách bình th ỏ ả ể ườ ế ộ

int ary[10] = {1,2,3,4,5,6,7,8,9,10};

ho cặ

int ary[] = {1,2,3,4,5,6,7,8,9,10};

ng trình s ụ ế ắ ả ả ạ ộ ứ ự tăng d n. Ch ầ ươ ử Ví d sau đây t o m t m ng m t chi u và s p x p m ng theo th t ộ d ng con tr và hàm malloc() đ gán b nh . ớ ụ ề ộ ể ỏ

#include #include

void main() {

int *p, n, i, j, temp; printf("\n Enter number of elements in the array: "); scanf("%d", &n); p = (int*) malloc(n * sizeof(int));

for(i = 0; i < n; ++i) {

printf("\nEnter element no. %d:", i + 1); scanf("%d", p + i); }

for(i = 0; i < n - 1; ++i) for(j = i + 1; j < n; ++j) if(*(p + i) > *(p + j)) {

temp = *(p + i); *(p + i) = *(p + j); *(p + j) = temp; }

for(i = 0; i < n; ++i) printf("%d\n", *(p + i)); }

Chú ý l nh ệ malloc():

p = (int*)malloc(n*sizeof(int));

đây, p đ c khai báo nh m t con tr tr đ n m t m ng và đ Ở ượ ỏ ỏ ế ư ộ ả ộ ượ c gán b nh s d ng malloc(). ớ ử ụ ộ

191

Con trỏ

D li u đ scanf(). ữ ệ ượ ọ vào s d ng c đ c ử ụ l nh ệ

scanf("%d",p+i);

Trong scanf(), bi n con tr đ c s d ng đ l u d li u vào trong m ng. ỏ ượ ử ụ ể ư ữ ệ ế ả

Các ph n t m ng đã l u tr đ ầ ử ả ữ ượ ư c hi n th b ng printf(). ị ằ ể

printf("%d\n", *(p + i));

ng h p này, vì giá tr l u trong v trí đó ph i đ c hi n th . Không có d u *, ả ượ ị ư ợ ị ể ấ ị Chú ý d u * trong tr ườ ấ printf() s hi n th đ a ch . ỉ ị ẽ ể ị

 free()

Hàm này có th đ c s d ng đ gi i phóng b nh khi nó không còn c n thi ể ượ ử ụ ể ả ầ ớ ộ ế . t

D ng t ng quát c a hàm free(): ủ ạ ổ

ượ ả void free( void *ptr ); i phóng không gian đ ptr đã s d ng tr ả ng lai. ử ụ ươ ể ử ụ i phóng này có th s d ng c gi c tr b i c đó b ng cách g i đ n malloc(), calloc(), ho c realloc(), ằ ỏ ở ptr, không gian đ ọ ế ặ Hàm free() gi trong t calloc() và realloc() (s đ ượ ướ c th o lu n sau). ậ ẽ ượ ả

i s h i b n có bao nhiêu s nguyên s đ ố ẽ ượ ạ ư ả c b n l u vào trong m t m ng. Sau đó ộ ng s nguyên, in chúng ra, và sau ướ ẽ ỏ ạ ớ ộ ằ ử ụ malloc và l u s l ư ố ượ ố Ví d bên d ụ s c p phát b nh đ ng b ng cách s d ng ẽ ấ đó xóa b nh c p phát b ng cách s d ng ộ ớ ấ ử ụ free. ằ ộ

#include #include /* required for the malloc and free functions */ int main() {

int number; int *ptr; int i;

printf("How many ints would you like store? "); scanf("%d", &number);

ptr = (int *) malloc (number * sizeof(int)); /*allocate memory*/

if(ptr != NULL) {

for(i = 0 ; i < number ; i++) { *(ptr+i) = i; }

for(i=number ; i>0 ; i--) { printf("%d\n", *(ptr+(i-1))); /*print out in reverse order*/

} free(ptr); /* free allocated memory */ return 0;

192

L p trình c b n C

ơ ả

} else

{

printf("\nMemory allocation failed - not enough memory.\n"); return 1; } }

K t qu nh sau n u giá tr đ 3: ả ư ị ượ ế ế c nh p vào ậ

How many ints would you like store? 3 2 1 0

 calloc()

c l u trong không ươ ự ị ượ ư nh calloc t ặ ư ớ malloc, c p phát b nh có th có giá tr b t kỳ. gian b nh đã c p phát là 0. V i ớ ấ ộ t chính là m c nhiên các giá tr đ ị ấ ư malloc, nh ng khác bi ệ ấ ng t ớ ể ộ

ố ấ ế ạ ớ ộ ỏ ố ố ố calloc đòi h i hai đ i s . Đ i s th nh t là s các bi n mà b n mu n c p phát b nh cho. Đ i s th hai là kích th ố ố ố ố ứ ấ c c a m i bi n. ỗ ướ ủ ứ ế

void *calloc( size_t num, size_t size );

ế ự ấ ỏ ỗ ộ ớ ư malloc, calloc s tr v m t con tr r ng (void) n u s c p phát b nh là thành công, i nó s tr v m t con tr NULL. Gi ng nh ố c l ng ượ ạ ẽ ả ề ộ ỏ ẽ ả ề ộ

i ch ra cho b n g i hàm ạ ế ỉ ử ế ớ c in ra trong vòng l p for. Ví d bên d ọ ụ d ng m t ch s m ng. Giá tr kh i t o c a vùng nh đã c p phát đ ở ạ ủ ụ calloc nh th nào và tham chi u đ n ô nh đã c p phát s ượ ướ ỉ ố ả ư ế ớ ấ ặ ấ ộ ị

#include #include int main() {

float *calloc1, *calloc2; int i;

calloc1 = (float *) calloc(3, sizeof(float)); calloc2 = (float *) calloc(3, sizeof(float)); if(calloc1 != NULL && calloc2 != NULL) {

for(i = 0; i < 3; i++) {

printf("\ncalloc1[%d] holds %05.5f ", i, calloc1[i]); printf("\ncalloc2[%d] holds %05.5f", i, *(calloc2 + i)); }

free(calloc1); free(calloc2); return 0;

} else {

193

Con trỏ

printf("Not enough memory\n"); return 1; }

}

K t qu : ế ả

calloc1[0] holds 0.00000 calloc2[0] holds 0.00000 calloc1[1] holds 0.00000 calloc2[1] holds 0.00000 calloc1[2] holds 0.00000 calloc2[2] holds 0.00000

t c các máy, các m ng calloc1 và calloc2 ph i ch a các giá tr 0. calloc đ c bi ấ ả ứ ả ị Trong t ệ ữ ụ t h u d ng khi b n đang s d ng m ng đa chi u. Đây là m t ví d khác minh h a cách dùng c a hàm calloc(). ộ ạ ử ụ ả ụ ặ ủ ề ả ọ

/* This program gets the number of elements, allocates spaces for the elements, gets a value for each element, sum the values of the elements, and print the number of the elements and the sum. */

#include #include main() {

int *a, i, n, sum = 0; printf(“\n%s%s”, “An array will be created dynamically. \n\n”, “Input an array size n followed by integers: ”);

scanf( “%d”, &n); /* get the number of elements */

a = (int *) calloc (n, sizeof(int)); /* allocate space */

/* get a value for each element */

for( i = 0; i < n; i++ ) {

printf(“Enter %d values: “, n); scanf(“%d”, a + i); }

/* sum the values */ for(i = 0; i < n; i++ ) sum += a[i];

free(a); /* free the space */

/* print the number and the sum */

printf(“\n%s%7d\n%s%7d\n\n”, “Number of elements: ”, n, “Sum of the elements: ”, sum); }

ả ử ư ậ

 realloc() s chúng ta đã c p phát m t s bytes cho m t m ng nh ng sau đó nh n ra là b n mu n thêm Gi ộ ặ các giá tr . B n có th sao chép m i th vào m t m ng l n h n, cách này không hi u qu . Ho c ộ

194

L p trình c b n C

ơ ả

ộ ố ọ ả ả ạ ệ ấ ể ố ả ứ ạ ơ ớ ị

realloc, mà d li u c a b n không ử ụ ể ấ ằ ọ ữ ệ ủ ạ b n có th c p phát thêm các bytes s d ng b ng cách g i hàm ạ b m t đi. ị ấ

ố ố ứ ố ố ứ ố ố ế ế ấ ậ ộ ỏ ớ ộ realloc() nh n hai đ i s . Đ i s th nh t là m t con tr tham chi u đ n b nh . Đ i s th hai là t ng s bytes b n mu n c p phát thêm. ổ ố ấ ạ ố

void *realloc( void *ptr, size_t size );

Truy n 0 nh là đ i s th hai thì t ng đ ng v i vi c g i hàm free. ố ố ứ ư ề ươ ươ ệ ọ ớ

i m t con tr NULL đ ả ề ộ ỏ ỗ ế c l ượ ạ ộ ỏ ượ c M t l n, ộ ầ realloc tr v m t con tr r ng (void) n u thành công, ng tr v . ả ề

calloc đ c p phát đ b nh cho m t m ng int có năm ph n t . Sau đó realloc ử ụ ầ ử ả ớ Ví d này s d ng đ ượ ọ ể ở ộ ể ấ ụ c g i đ m r ng m ng đ có th ch a b y ph n t ể ủ ộ ể ứ ả ộ . ầ ử ả

#include #include int main() {

int *ptr; int i;

ptr = (int *)calloc(5, sizeof(int *));

if(ptr!=NULL) {

*ptr = 1; *(ptr + 1) = 2; ptr[2] = 4; ptr[3] = 8; ptr[4] = 16;

/* ptr[5] = 32; wouldn't assign anything */

ptr = (int *)realloc(ptr, 7 * sizeof(int));

if(ptr!=NULL) {

printf("Now allocating more memory... \n"); ptr[5] = 32; /* now it's legal! */ ptr[6] = 64;

for(i = 0;i < 7; i++) { printf("ptr[%d] holds %d\n", i, ptr[i]);

} realloc(ptr, 0); /* same as free(ptr); - just fancier! */ return 0;

} else {

195

Con trỏ

printf("Not enough memory - realloc failed.\n"); return 1; }

} else {

printf("Not enough memory - calloc failed.\n"); return 1; } }

K t qu : ế ả

Now allocating more memory... ptr[0] holds 1 ptr[1] holds 2 ptr[2] holds 4 ptr[3] holds 8 ptr[4] holds 16 ptr[5] holds 32 ptr[6] holds 64

c s d ng khi kh i t o m ng: ptr[2] = 4 là t ng đ ng v i *(ptr + 2) ượ ử ụ ở ạ ả ươ ươ ớ

196

L p trình c b n C

ơ ả

c khi s d ng realloc, vi c gán m t giá tr đ n ph n t ptr[5] không gây ra l i cho trình biên ị ế ệ ộ ỗ ử ụ ng trình v n th c thi, nh ng ptr[5] không ch a giá tr mà b n đã gán. Chú ý hai cách khác nhau đ = 4 (ch d đ c h n!). ỉ ễ ọ ơ Tr ướ d ch. Ch ị ươ ầ ử ứ ự ư ạ ẫ ị

Tóm t ắ t bài h c ọ

 M t con tr cung c p m t ph ỏ ấ ộ ươ ự ế ng th c truy xu t m t bi n mà không c n tham chi u tr c ti p ứ ế ế ầ ấ ộ ộ đ n bi n. ế ế

 S khai báo con tr bao g m m t ki u

 M t con tr là m t bi n, ch a đ a ch vùng nh c a m t bi n khác. ứ ị ớ ủ ế ế ỏ ộ ộ ộ ỉ

ể d li u ữ ệ c s , m t d u *, và m t tên bi n. ộ ấ ơ ở ự ế ồ ỏ ộ ộ

 Có hai toán t đ c bi c dùng v i con tr : * và &. ử ặ t đ ệ ượ ớ ỏ

 Toán t & tr v đ a ch b nh c a toán h ng. ử ả ề ị ớ ủ ỉ ộ ạ

 Toán t nh đ ớ ượ

&. Nó tr v giá tr đ c ch a trong v trí b ủ ầ ổ ử ả ề ị ượ ứ ị ộ th hai, *, là ph n b xung c a toán t ử ứ c tr b i con tr . ỏ ỏ ở

 Ch có phép c ng và phép tr là có th đ ể ượ ừ ộ ỉ c th c thi v i con tr . ỏ ớ ự

 Hai con tr có th đ ể ượ ứ ế ể ệ ả ộ ỉ ỏ đ n các bi n có cùng ki u d li u. ế c so sánh trong m t bi u th c quan h ch khi c hai bi n này cùng tr ể ữ ệ ỏ ế

 Các con tr đ c truy n t ỏ ượ ề ớ i hàm nh các đ i s . ố ố ư

 M t tên m ng th t ra là m t con tr tr đ n ph n t ỏ ỏ ế ầ ử ầ đ u tiên c a m ng. ủ ả ả ậ ộ ộ

 M t h ng con tr là m t đ a ch ; m t bi n con tr là m t n i đ l u đ a ch . ỉ ộ ộ ơ ể ư ị ộ ằ ộ ị ế ỏ ỏ ỉ

197

Con trỏ

c c p phát khi c n dùng b ng cách dùng các hàm malloc(),calloc(),realloc(). ộ ầ  B nh có th đ ớ S c p phát b nh theo cách này đ c g i là s c p phát b nh đ ng. ể ượ ấ ớ ự ấ ộ ằ ự ấ ượ ọ ớ ộ ộ

Ki m tra ti n đ h c t p ế ộ ọ ậ ể

ấ ộ ươ ế ng th c truy xu t m t bi n mà không tham chi u tr c ti p ứ ự ế ế ấ ộ 1. M t _________ cung c p m t ph đ n bi n. ế ộ ế

2. Các con tr không th tr đ n các m ng.

A. M ngả C. C u trúc ấ B. Con trỏ D. T t c đ u sai ấ ả ề

(Đúng/Sai) ể ỏ ế ả ỏ

3. __________ c a con tr xác đ nh ki u c a các bi n mà con tr có th tr đ n. ể ỏ ế ể ủ ủ ế ỏ ỏ ị

4. Có hai toán t

A. Ki uể C. N i dung ộ B. Kích th cướ D. T t c đ u sai ấ ả ề

đ c bi c dùng v i con tr là ử ặ t đ ệ ượ ỏ ____ và _____. ớ

A. ^ và % C. * và & B. ; và ? D. T t c đ u sai ấ ả ề

5. Ch có ________ và __________ là nh ng phép toán có th đ ể ượ ữ ỉ c th c hi n trên các con tr . ỏ ự ệ

A. C ng, Tr ừ ộ C. Chia, C ngộ B.Nhân, Chia D. T t c đ u sai ấ ả ề

có th đ đ n các ki u d li u khác ỏ ể ượ c so sánh ch khi c hai bi n này đang tr ả ế ỉ ỏ ế ữ ệ ể 6. Hai con tr nhau.

(Đúng/Sai)

ng trình có yêu c u đ ộ ớ ươ ầ ượ c g i là ọ 7. S c p phát b nh theo cách này, nghĩa là, khi trong ch ự ấ __________ .

198

L p trình c b n C

ơ ả

ớ ộ A. C p phát b nh đ ng ộ C. C p phát b nh n i dung ộ ớ ộ ớ ộ ấ ấ B. C p phát b nh tĩnh ấ D. T t c đ u sai ấ ả ề

Bài t p t làm ậ ự

ng trình đ nh n vào m t chu i và in ra nó n u đó là chu i đ c xuôi – ng ươ ỗ ọ ể ế ậ ộ ỗ ượ c 1. Vi t m t ch ế ộ đ u gi ng nhau. ố ề

ế t m t ch ộ ộ ng trình s d ng con tr tr đ n các chu i đ nh n tên c a m t con thú và m t ỗ ể ủ ậ ộ 2. Vi con chim và tr v các tên theo d ng s nhi u. ử ụ ạ ươ ả ề ỏ ỏ ế ề ố

199

Con trỏ

Ngu n Maths.vn ồ