Xin chào mọi người!
Ở bài trước mình đã giới thiệu tổng quát về Con trỏ trong C++ rồi 😀 Mình muốn các bạn hiểu thật sâu về con trỏ nên nếu ai đọc qua về con trỏ thì vào đây (Con trỏ Phần 1) để xem nhé!

3. Lấy giá trị con trỏ

Mọi biến, hằng trong C++ đều có địa chỉ riêng của nó. Hình dưới đây thể hiện rõ điều này
Biến val trong hình có giá trị bằng 5, nhưng đồng thời nó cũng lưu địa chỉ của nó trong bộ nhớ RAM là 0xFE, sau đó ta khởi tạo 1 con trỏ ptr và giá trị của nó chính là địa chỉ của biến val (0xFE). Ta gọi con trỏ ptr đang “trỏ” tới biến val.
Để lấy địa chỉ của một biến, hằng trong C++, ta chỉ việc thêm dấu & trước tên biến, hằng. Ở hình trên, con trỏ ptr trỏ tới biến val bằng cách ghi&val.
Vậy, sau khi trỏ vào rồi, ta làm gì với con trỏ đây?
Lúc này, con trỏ ptr cũng giống như biến val. Ta thao tác với biến val như thế nào, con trỏ ptr cũng bị tác động như thế đấy, và ngược lại. Ví dụ:
Mã nguồn:
1
2
3
4
5
int val = 5;
int *ptr = &val;
*ptr = 6;
 
cout << val; // = 6???
Ở ví dụ trên, mình muốn lưu ý với các bạn 1 điều, ptr lưu giữ địa chỉ của biến val, nên nếu muốn truy xuất tới giá trị mà ptr trỏ tới, ta cần phải thêm toán tử * vào trước tên con trỏ. Với val++ tương đương với (*p)++ (cần thiết phải có dấu ngoặc tròn, vì toán tử ++ có độ ưu tiên thấp hơn*, với lại nhìn cũng sáng sủa, dễ hiểu hơn :D).

4. Kiểu dữ liệu con trỏ

Với các biến thường, ta có những kiểu như int, long, double, char,… Cũng tương tự, con trỏ cũng có kiểu dữ liệu int*long*double*char*,… Con trỏ chỉ được phép trỏ tới biến cùng kiểu dữ liệu, trừ con trỏ void (chỉ trỏ lung tung thế thì bất lịch sự lắm :v).
Tuy có nhiều kiểu dữ liệu cho con trỏ như thế, nhưng bất kỳ con trỏ nào cũng đều có kích thước 4 byte. Nghe thì hơi ngộ nhưng nếu các bạn chịu khó suy nghĩ thì sẽ thấy rất bình thường :D. Giá trị của con trỏ đều là địa chỉ của biến nó trỏ đến, cho nên dù là con trỏ kiểu gì thì nó cũng chỉ chứa giá trị địa chỉ thôi 😀 (nếu các bạn muốn kiểm chứng, sử dụng hàm sizeof() mà mình đã giới thiệu ở Bài 2 – Kiểu dữ liệu, biến và hằng trong C++).
Giả sử như chúng ta có 3 biến kiểu int, long, char. Nếu muốn sử dụng con trỏ để trỏ tới 3 biến này, theo lý thuyết ta phải dùng tới 3 con trỏ kiểu int*, long* và char*. Vậy có cách nào tối ưu hơn không?
Trong C++ có hỗ trợ 1 kiểu dữ liệu đặc biệt dành cho con trỏ, đó là con trỏ void. Nó có thể trỏ tới mọi biến, dù cho các biến khác kiểu dữ liệu. Tuy nhiên, có 1 lưu ý dành cho con trỏ void, mình xin đưa ra ví dụ sau:
Mã nguồn:
1
2
3
4
int a = 10;
void *pVoid = &a; // Con trỏ void pVoid trỏ vào biến a
int *p = pVoid; // Lỗi
cout << *p << endl;
Ớ ví dụ trên, con trỏ p muốn trỏ tới biến a, nên nó gán giá trị bằng pVoid (vì con trỏ pVoid đang trỏ đến biến a). Tuy nhiên vì con trỏ void không biết kiểu dữ liệu của nó trỏ đến là gì, cho nên trình biên dịch sẽ báo lỗi khi gán 2 con trỏ khác kiểu dữ liệu. Để khắc phục điều này, ta cần phảiép kiểu:
Mã nguồn:
1
2
3
4
int a = 10;
void *pVoid = &a; // Con trỏ void pVoid trỏ vào biến a
int *p = (int*)pVoid; // Ép kiểu int*
cout << *p << endl;
Lúc này trình biên dịch sẽ chạy hoàn toàn bình thường. Cần lưu ý khi sử dụng con trỏ void nhé 😀
Bản thân mình biết về con trỏ cũng không nhiều, nên mình chỉ viết theo những gì mình biết. Nếu có điều gì sai sót, mong các bạn comment phía bên dưới, mình sẽ chỉnh sửa lại trong thời gian ngắn nhất! Con trỏ về lý thuyết còn rất nhiều, mình sẽ đề cập nó sau, ở trong bài Mảng và Chuỗi 😀
Trên đây là bài viết về Con trỏ – Phần 2. Cảm ơn các bạn đã chú ý theo dõi!
Đánh giá bài viết này để tác giả có động lực hơn nhé!
Axact

Administrator:

Xin chào, tôi là Nguyễn Quý Quang Huy. Tôi 14 tuổi và sinh sống tại Hoài Đức, Hà Nội. Tôi lập ra Rinne-IT Blog này nhằm chia sẻ những kiến thức mình có và những bài viết hay trên mạng do tôi tổng hợp. Blog đang trong giai đoạn phát triển nên nếu có lỗi mong các bạn bỏ qua. Tôi luôn chào đón những ý kiến phát triển từ từ các bạn. Giờ thì hãy khám phá blog của tôi nào ^_^

Bình Luận:

0 bình luận: