Ý kiến rất cá nhân của tôi là hình ảnh với mũi tên chỉ theo cách này hoặc làm cho con trỏ khó hiểu hơn. Nó làm cho chúng có vẻ giống như một số thực thể trừu tượng, bí ẩn. Họ không phải.
Giống như mọi thứ khác trong máy tính của bạn, con trỏ là số . Tên "con trỏ" chỉ là một cách hay để nói "một biến chứa địa chỉ".
Do đó, hãy để tôi khuấy động mọi thứ xung quanh bằng cách giải thích cách máy tính thực sự hoạt động.
Chúng ta có một int
, nó có tên i
và giá trị 5. Điều này được lưu trữ trong bộ nhớ. Giống như mọi thứ được lưu trữ trong bộ nhớ, nó cần một địa chỉ hoặc chúng ta sẽ không thể tìm thấy nó. Hãy nói rằng i
kết thúc tại địa chỉ 0x12345678 và bạn thân của nó j
với giá trị 6 kết thúc ngay sau nó. Giả sử CPU 32 bit trong đó int là 4 byte và con trỏ là 4 byte, thì các biến được lưu trữ trong bộ nhớ vật lý như thế này:
Address Data Meaning
0x12345678 00 00 00 05 // The variable i
0x1234567C 00 00 00 06 // The variable j
Bây giờ chúng tôi muốn chỉ vào các biến này. Chúng ta tạo một con trỏ tới int int* ip1
và một int* ip2
. Giống như mọi thứ trong máy tính, các biến con trỏ này cũng được phân bổ ở đâu đó trong bộ nhớ. Giả sử rằng chúng kết thúc tại các địa chỉ liền kề tiếp theo trong bộ nhớ, ngay sau đó j
. Chúng tôi đặt các con trỏ chứa địa chỉ của các biến được phân bổ trước đó: ip1=&i;
("sao chép địa chỉ của i vào ip1") và ip2=&j
. Điều gì xảy ra giữa các dòng là:
Address Data Meaning
0x12345680 12 34 56 78 // The variable ip1(equal to address of i)
0x12345684 12 34 56 7C // The variable ip2(equal to address of j)
Vì vậy, những gì chúng ta nhận được chỉ là một số bộ nhớ 4 byte chứa các số. Không có mũi tên thần bí hay ma thuật ở bất cứ đâu trong tầm nhìn.
Thực tế, chỉ bằng cách nhìn vào một bãi chứa bộ nhớ, chúng ta không thể biết được địa chỉ 0x12345680 có chứa int
hay không int*
. Sự khác biệt là cách chương trình của chúng tôi chọn sử dụng nội dung được lưu trữ tại địa chỉ này. (Nhiệm vụ của chương trình của chúng tôi thực sự chỉ là nói cho CPU biết phải làm gì với những con số này.)
Sau đó, chúng tôi thêm một mức độ gián tiếp với int** ipp = &ip1;
. Một lần nữa, chúng ta chỉ nhận được một đoạn ký ức:
Address Data Meaning
0x12345688 12 34 56 80 // The variable ipp
Các mô hình có vẻ quen thuộc. Một đoạn khác gồm 4 byte chứa một số.
Bây giờ, nếu chúng ta có một bộ nhớ trong bộ nhớ RAM giả tưởng ở trên, chúng ta có thể kiểm tra thủ công những con trỏ này ở đâu. Chúng tôi xem những gì được lưu trữ tại địa chỉ của ipp
biến và tìm nội dung 0x12345680. Tất nhiên đó ip1
là địa chỉ được lưu trữ. Chúng ta có thể đến địa chỉ đó, kiểm tra nội dung ở đó và tìm địa chỉ của i
, và cuối cùng chúng ta có thể đến địa chỉ đó và tìm số 5.
Vì vậy, nếu chúng ta lấy nội dung của ipp *ipp
, chúng ta sẽ nhận được địa chỉ của biến con trỏ ip1
. Bằng cách viết, *ipp=ip2
chúng tôi sao chép ip2 vào ip1, nó tương đương với ip1=ip2
. Trong cả hai trường hợp, chúng tôi sẽ nhận được
Address Data Meaning
0x12345680 12 34 56 7C // The variable ip1
0x12345684 12 34 56 7C // The variable ip2
(Những ví dụ này đã được đưa ra cho một CPU endian lớn)
ipp
khi xác định nó, để câu hỏi của bạn hoàn tất ;-)