[Stanford] Làm việc với con trỏ và kí tự trong lập trình c++

Trong bài học này, tôi sẽ hướng dẫn các bạn học lập trình c++ tìm hiểu một số vấn đề khi sử dụng con trỏ trỏ đến mảng kí tự (C-style string).

C-style string symbolic constants

C-style string là một trường hợp đặc biệt của mảng một chiều, được ngôn ngữ C++ hổ trợ một số đặc điểm nhằm giúp lập trình viên thao tác với C-style string một cách thuận tiện hơn.

Ngoài cách khởi tạo mảng một chiều thông thường, C-style string còn có thể khởi tạo bằng một hằng chuỗi kí tự như sau:

1

char

myKiTu

[

]

=

“Stanford Day lap trinh”

;

Chuỗi kí tự “Stanford Day lap trinh” được xem như là một chuỗi hằng kí tự, nó có địa chỉ cụ thể trên bộ nhớ ảo, nó được lưu trên bộ nhớ ảo, nhưng không có tên biến để truy xuất đến địa chỉ của chuỗi hằng kí tự này. Nhưng sau khi sử dụng chuỗi hằng kí tự “Stanford Day lap trinh” để khởi tạo cho mảng myKiTu, mảng arrKiTu không được khai báo là kiểu chuỗi hằng kí tự (const char []) nên các kí tự trong mảng myKiTu hoàn toàn có thể bị thay đổi.

Ví dụ như sau:

1

2

char

myKiTu

[

]

=

“Stanford Day lap trinh”

;

myKiTu

[

1

]

=

‘T’

;

//=> “STanford Day lap trinh”

Điều này chứng tỏ mảng myKiTu được cấp phát bộ nhớ tại địa chỉ khác chuỗi hằng kí tự “Stanford Day lap trinh”, việc khởi tạo mảng kí tự bằng một chuỗi hằng kí tự chỉ đơn giản là copy từng kí tự của chuỗi “Stanford Day lap trinh” và đưa vào mảng.

Do đó, con trỏ kiểu char (char *) trỏ đến mảng myKiTu và trỏ đến vùng nhớ của chuỗi hằng kí tự “Stanford Day lap trinh” là 2 trường hợp khác nhau.

Tôi lấy ví dụ một con trỏ kiểu char (char *) trỏ đến mảng myKiTu trong lập trình c++ với code xử lý như sau:

1

2

3

4

5

char

myKiTu

[

]

=

“Stanford Day lap trinh”

;

char

*

pr

=

myKiTu

;

 

pr

[

1

]

=

‘T’

;

cout

<<

myKiTu

<<

endl

;

Khi chạy chương trình sẽ in ra được chuỗi có tên: STanford Day lap trinh

Như vậy, con trỏ pr sau khi trỏ đến mảng myKiTu thì có thể thay đổi giá trị bên trong vùng nhớ mà mảng myKiTu đang nắm giữ, vì vùng nhớ này không phải là vùng nhớ hằng.

Trường hợp tiếp theo, tôi sẽ cho một con trỏ kiểu char (char *) trỏ trực tiếp đến chuỗi hằng kí tự:

1

2

3

4

char

*

pr

=

“Stanford Day lap trinh”

;

pr

[

1

]

=

‘T’

;

 

cout

<<

pr

<<

endl

;

Khi chạy dòng code trên sẽ bị lỗi. Nguyên nhân là do vùng nhớ lưu trữ chuỗi kí tự “Stanford Day lap trinh” là vùng nhớ hằng, giá trị bên trong vùng nhớ này không thể thay đổi, trong khi đó lệnh myKiTu[1] = 'T'; cố gắng thay đổi giá trị bên trong vùng nhớ hằng.

Đến đây có thể có một số bạn thắc mắc về địa chỉ của chuỗi hằng kí tự “Stanford Day lap trinh” mà tôi sử dụng. Mặc dù chuỗi hằng kí tự không được khai báo như một biến thông thường, nhưng nó được tạo ra và có địa chỉ cụ thể trên vùng nhớ ảo. Chúng ta truy xuất địa chỉ của chuỗi hằng kí tự bằng chính nội dung của chuỗi đó:

1

2

3

4

5

6

7

8

int

main

(

)

{

cout

<<

&

(

“Stanford Day lap trinh”

)

<<

endl

;

cout

<<

&

(

“STanford Day lap trinh”

)

<<

endl

;

 

system

(

“pause”

)

;

return

0

;

}

Kết quả hiển thị trên máy tính của tôi là:

1

2

0x405061

0x405078

Như vậy, mỗi chuỗi hằng kí tự có nội dung khác nhau sẽ có một địa chỉ khác nhau. Chúng ta có thể sử dụng nội dung của chuỗi hằng kí tự này như mảng một chiều, nhưng không thể thay đổi nội dung của nó.

std::cout and char pointers

Với các mảng một chiều có kiểu dữ liệu khác, để xem được nội dung bên trong mảng, chúng ta cần sử dụng vòng lặp để duyệt từng phần tử bên trong mảng. Ví dụ:

1

2

3

4

5

6

7

float

arr

[

]

=

{

1.2

,

1.6

,

2.8

,

3.6

}

;

int

size

=

sizeof

(

arr

)

/

sizeof

(

arr

[

0

]

)

;

 

for

(

int

i

=

0

;

i

<

size

;

i

++

)

{

cout

<<

arr

[

i

]

<<

” “

;

}

Đối với mảng kí tự (C-style string) chúng ta có thể in toàn bộ nội dung của mảng bằng cách sử dụng đối tượng cout như sau:

1

2

char

str

[

]

=

“Lam viec voi ki tu va con tro trong c”

;

cout

<<

str

<<

endl

;

Đối với các kiểu dữ liệu không phải kiểu con trỏ char (char *), đối tượng cout chỉ in ra địa chỉ của mảng (vì arr tương đương với &arr), nhưng với kiểu con trỏ char (char *), đối tượng cout có cách định nghĩa khác.

Trong lập trình c++ đối tượng cout chỉ hổ trợ cho kiểu con trỏ char (char *), nhưng vì sử dụng tên mảng str tương đương với &str. Như các bạn biết, toán tử address-of trả về kiểu con trỏ, nên str truyền vào đối tượng cout được xem là con trỏ kiểu char (char *).

1

2

3

4

5

char

str

[

]

=

“Chao cac ban !”

;

char

*

pr

=

str

;

 

cout

<<

str

<<

endl

;

cout

<<

pr

<<

endl

;

Khi chạy chương trình sẽ có được 2 dòng có nội dung giống nhau là: Chao cac ban !

Điều này dẫn để một hệ quả, chúng ta không thể in ra địa chỉ của một biến kiểu kí tự (char) vì khi đó nó coi địa chỉ của biến như một C-style string nên in ra theo kiểu kí tự đến khi gặp dấu \0 thì kết thúc.

1

2

3

    

//Khai biế kí tự

    

char

ch

=

‘A’

;

    

cout

<<

“Dia chi: “

<<

&ch

<<

endl

;

Khi đó muốn hiển thị được địa chỉ của một biến kí tự các bạn có thể sử dụng 2 cách trong đoạn code như sau:

1

2

cout

<<

“Dia chi: “

<<

(

void

*

)

&ch

<<

endl

;

cout

<<

“Dia chi: “

<<

static_cast

<

void

*

>

(

&ch

)

<<

endl

;

Kết quả hiển thị trong 2 trường hợp:

Hy vọng qua bài viết này các bạn học lập trình c++ đã hiểu rõ hơn về kiểu con trỏ, mảng kí tự sử dụng C-style string trong lập trình c++. Bên cạnh đó các bạn muốn học lập trình qua dự án cùng chuyên gia giỏi, giàu kinh nghiệm của Stanford có thể tham gia khóa tại đây: khóa học c++

 

=============================
☎ STANFORD – ĐÀO TẠO VÀ PHÁT TRIỂN CÔNG NGHỆ
Hotline: 0963 723 236 – 0866 586 366
Website: https://stanford.com.vn
Facebook: http://bit.ly/2FN0TYb
Youtube: http://bit.ly/2TkKT7I

5

/

5

(

1

vote

)