Con trỏ (pointer) từ cơ bản tới nâng cao phần 1

Share:
Chắc hẳn nếu ai đã từng lập trình C/C++ thì đã từng nghe qua về con trỏ (hay pointer). Đây có thể nói là một trong những phần khó nhất trong C. Đại khái là nó khó hiểu và dễ quên nữa. Vậy làm cách nào để bạn biết và hiểu về con trỏ, làm thế nào để bạn có thể hoàn thành tốt các kì phỏng vấn cho một kĩ sư lập trình nhúng, mà khi người ta hỏi tới C, thì 90% là hỏi về con trỏ. Ôi **. hahaha.

Con trỏ là gì?

Câu trả lời, con trỏ là một biến nguyên bình thường, nó chứa một giá trị trong đó. Vậy giá trị nó lưu trong đó là gì? Câu trả lời là địa chỉ của một ô nhớ. Ta lập trình trên ARM 32 bit, thì con trỏ chứa giá trị 32 bit (8 số hex).
Ủa, vậy tại sao lại có char*, int*, void*, double*, vv? Câu trả lời là: con trỏ chứa địa chỉ, con trỏ kiểu char trỏ tới "vùng nhớ" kiểu char (nghĩa là các ô nhớ ở đây chứa dữ liệu kiểu char), con trỏ kiểu int thì trỏ tới vùng nhớ kiểu int....

Chúng ta đi sâu hơn về bộ nhớ (memory)


Nhìn vào hình và ta sẽ giải thích như sau:
1. Khi chúng ta khai báo một biến, máy tính sẽ tạo ra một vùng nhớ để lưu giá trị cho biến đó (hay còn gọi là cấp phát bộ nhớ).
2. Nếu biến được khai báo trong hàm main(), thì những ô nhớ được cấp phát sẽ nằm trong vùng stack (như trong hình là biên x)
3. Nếu biến được khai báo ngoài hàm main() và ngoài tất cả các hàm, thì những ô nhớ được cấp phát sẽ nằm trong vùng global của bộ nhớ (trong hình là biến y).

Giả sử máy tính cấp phát cho biến x một "vị trí" (vị trí này chính là địa chỉ đấy - địa chỉ của vùng nhớ, tại sao mình không nói là ô nhớ, bởi vì tùy vào CPU mà kiểu int có thể được chứa ở nhiều ô nhớ) là 4,100,000. Chúng ta đã gán 4 vào x thì cái "vị trí" 4,100,000 sẽ lưu giá trị 4.
Và...con trỏ là cái thứ lưu cái số 4,100,000 như ví dụ ở trên đấy! Nếu muốn trỏ tới thằng x, thì phải dùng con trỏ kiểu int, bởi vì giá trị của x là integer.

Khai báo con trỏ




Kiểu dữ liệu ở đây bao gồm:
- Kiểu dữ liệu có sẵn: int, char, void, long, ....
- Kiểu dữ liệu do chúng ta tự định nghĩa: struct, union.
- Kiểu dữ liệu là lớp (class) do chúng ta định nghĩa (c++).
- Kiểu dữ liệu dẫn xuất, kiểu con trỏ hàm (nâng cao).
Ví dụ:



- p ở đây là con trỏ, và con trỏ p này trỏ đến vùng nhớ kiểu int. Lưu ý *p không phải là con trỏ mà là giá trị của vùng nhớ mà con trỏ p trỏ tới (giả sử p trỏ tới thằng x trong hình đầu thì *p = 4 nhé!).

Tiếp ví dụ:


Khởi tạo giá trị cho biến con trỏ

Khởi tạo (initialize) khác với khai báo (declared) các bạn nhé! Sau khi khai báo 1 biến, bạn gán giá trị lần đầu tiên cho biến đó thì gọi là khởi tạo! Mình khuyên các bạn nên khởi tạo biến mỗi khi khai báo, vì khi không khởi tạo, nhiều trình biên dịch sẽ tự khởi tạo một giá trị rác cho biến đó, hoặc nhiều khi gây lỗi.
Khởi tạo cho con trỏ:


- Toán tử lấy địa chỉ: toán tử & 1 ngôi (unary operator), toán tử này hoàn toàn khác với toán tử & 2 ngôi (bitwise).
ví dụ:

- Lúc này *conTro tương đương với bienInteger, mọi thao tác với *conTro cũng chính là thao tác với bienInteger, hay mọi thao tác với bienInteger cũng chính là thao tác với *conTro.
- Câu lệnh bienInteger = 5; hoàn toàn tương đương với *conTro = 5;.
- bienInteger++; hoàn toàn tương đương với (*conTro)++; (Khác với *conTro++ nhé!).


Tham khảo:
diendan.congdongcviet.com

3 nhận xét:

  1. em muốn khai báo con trỏ cấp 100 thì dùng ***...***(100 sao de tạo à ad ) có cách nào ngắn gọn như là 100* để thể hiện cấp 100 ko ad ?(em muốn tìm cách để khai báo con trổ cấp cao cho đỡ mệt ấy ạ)

    Trả lờiXóa
    Trả lời
    1. Anh cũng chưa nghĩ ra cách nào như em nói. Em có biết thì chia sẻ cho anh với nha. Anh thấy ở ngoài thực tế cũng không ai chơi tới 100 level như em hết :v

      Xóa