Chương 10: Con Trỏ
Có thể bạn quan tâm
| | Programming in C | ? 2003 Kishori Mundargi |
CHƯƠNG 10:
Con trỏ
Một con trỏ là biến trong C , nó trỏ đến một vùng nhớ. Con trỏ không trực tiếp lưu trữ giá trị như int hay float. Chúng ta có thể truy cập gián tiếp một giá trị thông qua một biến con trỏ.
Một con trỏ được khai báo như sau :
int *ptr1; int i; ptr1 = &i;
Ở đây bạn phải hiểu được vai trò của các ký tự '*' và '&' ở phí trước các biến. Kí tự '*' ở phía trước biến được sử dụng để khai báo một biến con trỏ. Kí tự '*' cũng được dùng phía trước một biến con trỏ để truy cập và lấy về giá trị được lưu bởi biến con trỏ chứ không phải địa chỉ của nó (i.e. địa chỉ được gọi thông qua tên của nó không kèm theo '*'). Ngược lại, kí tự '&' được sử dụng để truy cập tới địa trỉ của một biến nguyên được trỏ tới bởi con trỏ. Trong ví dụ trên, bạn khai báo một con trỏ nguyên "ptr1" là một biến nguyên "i". Sau đó bạn tạo một con trỏ ptr1 trỏ tới địa chỉ của biến i. Lưu ý tới ví dụ phía trên để hiểu khái niệm này.
Chương trình 10.1
|
|
Chương trình phía trên cho kết quả sau
The value of i is 3 The pointer ptr1 contains the value 3
Kết quả trên minh họa cho việc con trỏ ptr1 trỏ đến địa chỉ của biến i. Như vậy '&' được coi như là toán tử địa chỉ của
Các hàm sử dụng con trỏ
Bạn đã biết là một hàm chỉ có thể trả về một giá trị. Nếu bạn muốn một hàm có thể thay đổi cho nhiều hơn một biến, bạn có thể truyền các con trỏ cho hàm để làm điều đó. Hàm này sẽ không thay đổi các con trỏ nhưng có thể thay đổi nội dung của các con trỏ này trỏ tới
Theo dõi ví dụ sau để thấy việc truyền 2 con trỏ nguyên iptr1 và iptr2 cho hàm có tên là swap.
Chương trình 10.2
|
|
Note: Bất cứ khi nào bạn gọi một hàm mà nó nhận một con trỏ làm tham số, bạn phải truyền địa chỉ của một biến cho nó.
Hàm sẵn có scanf() nhận tham số thứ 2 là một con trỏ tới một biến. Xem câu lệnh sau scanf("%f",&Total); Vừa rồi bạn đã truyền địa chỉ của biến Total, nếu bạn truyền biến Total, thì một lỗi dạng (core dump) sẽ xuất hiện khi thực thi chương trình. Về bản chất đây là một lỗi bộ nhớ trong một hệ thống UNIX. scanf("%f",Total); // Results in core dump error !
Con trỏ và mảng
Trong C, các con trỏ và mảng có mối liên hệ khá gần gũi. Các con trỏ rất hữu ích trong việc thao tác với mảng. Việc khai báo một con trỏ tới một mảng thì giống như với một con trỏ nguyên hay con trỏ số thực.
int *ptr; int arr[5]; ptr = &arr[0];Như bạn thấy ở trên, con trỏ chứa địa chỉ của phần tử đầu tiên của mảng. C cung cấp một cách khác để trỏ tới phần tử đầu tiên của mảng, ptr = arr;
Ghi chú: Cần nhớ rằng tên của một con mảng mà không có kèm chỉ số thì nó là một con trỏ trỏ tới phần tử đầu tiên của mảng.
Khi một con trỏ được thiết lập trỏ tới một phần tử của một mảng thì có thể dùng toán tử tăng ++ và giảm -- để trỏ tới các phần tử liền sau hoặc liền trước tương ứng trong mảng, . Nhưng việc tăng giảm con trỏ để trỏ vượt quá cỡ của mảng sẽ sinh một lỗi runtime, và chương trình của bạn sẽ có thể treo (crash) hoặc ghi đè lên các dữ liệu khác hoặc đoạn mã khác của chương trình của bạn. Vì thế lập trình viên phải đảm bảo mình sử dụng con trỏ tới một mảng một cách thành thạo.
Một nhân tố khác phải cân nhắc đó là kích thước của dữ liệu mà con trỏ trỏ tới. Giả sử rằng một con trỏ nguyên trỏ tới một mảng nguyên; khi bạn tịnh tiến con trỏ lên, con trỏ sẽ trỏ tới phần tử tiếp theo trong mảng. Nhưng thực tế, con trỏ đó sẽ lưu giá trị mà thường là sẽ lớn hơn 4 byte so với địa chỉ phần tử đầu tiên của mảng.
Quy tắc biến đổi mảng
Nếu arr1 là một mảng, thì biểu thức arr1 + 1 sẽ cho địa chỉ của phần tử thứ 2 trong mảng bất kể kiểu dữ liệu của arr1. Bây giờ chúng ta có thể sử dụng toán tử gián tiếp * đứng phía trước tên biến để lấy giá trị được chứa trong địa chỉ này. Như vậy *(arr1 + 1) sẽ cho giá trị được lưu trong phần tử thứ 2 của mảng. Cặp ngoặc đơn là bắt buộc bởi vì toán tử * có độ ưu tiên cao hơn toán tử cộng. Vì thế chúng ta có thể sử dụng quy tắc biến đổi này để chuyển đổi bất cứ mảng nào được tham chiếu tới bằng các biểu thức với con trỏ tương đương.
arr1[0] tương đương với *(arr1 + 0) arr1[1] tương đương với *(arr1 + 1) arr1[2] tương đương với *(arr1 + 2)
Nếu không có cặp ngoặc đơn thì phép toán *arr1 + 1 sẽ cho một kết quả khác hoàn toàn, giống như lấy giá trị được lưu bởi phần tử đầu tiên của mảng và cộng thêm 1.
Cấp phát bộ nhớ và con trỏ
Định nghĩa mảng cho ta biết một khối nhớ được dự trữ riêng bởi hệ điều hành trong quá trình bắt đầu thực thi chương trình, điều này không xảy ra nếu mảng được đại diện bởi một biến con trỏ Việc sử dụng một biến con trỏ yêu cầu lập trình viên phải thực hiện một số kiểu cấp phát bộ nhớ trước khi các phần tử mảng được sử dụng. Phương thức này gọi là Cấp phát bộ nhớ động . Hàm malloc() trong thư viện hàm C chuẩn được sử dụng cho mục đích này.
Chương trình 10.3
|
|
Ghi chú: hàm malloc() cần phải có kiểu dữ liệu giống với kiểu của biến con trỏ.
Sự khác nhau giữa mảng và con trỏ
Có một số khác biệt chủ yếu giữa mảng và con trỏ. Một giá trị của con trỏ có thể bị thay đổi khi nó trỏ tới vùng nhớ khác. Nhưng con trỏ được đại diện bởi tên một mảng thì không thể bị thay đổi. Nó được xem như một hằng.
float TotAmt[10]; TotAmt ++; // cau lenh khong hop le TotAmt -= 1; // cau lenh hop le
Một điểm khác cần nhớ đó là tên của mảng được khởi tạo bằng cách trỏ tới phần tử đầu tiên của mảng trong khi con trỏ không được khởi tạo khi khai báo. Chúng phải được khởi tạo tường minh trước khi sử dụng nếu không một lỗi run-time sẽ xuất hiện.
Kiểm tra ngắn
Câu hỏi luyện tập
Bài tập
Lời giải bài tập
[Ý kiến đóng góp của bạn rất quan trọng với chúng tôi. Nếu có nhận xét, góp ý hay thắc mắc liên quan tới chương này, xin vui lòng gửi email tới [email protected] .]
| Phần trước: Chuỗi | Phần tiếp theo: Phép toán trên các bit |
Từ khóa » Toán Tử Trong Con Trỏ
-
Toán Tử Con Trỏ Trong C++
-
8.1 Toán Tử Tăng, Giảm Dùng Cho Con Trỏ - Khóa Học C++
-
8.0 Con Trỏ - Khóa Học C++
-
C Cơ Bản: Toán Tử Tăng Giảm Của Con Trỏ - DevIOT
-
Các Phép Toán Trên Con Trỏ Và Chỉ Mục Mảng Trong C++ (Pointers ...
-
Con Trỏ Cơ Bản Trong C++ | How Kteam
-
Con Trỏ Trong C++ - Viblo
-
Toán Tử Con Trỏ Trong C++ | CppDeveloper
-
Bài 11: Con Trỏ Trong C - Học Lập Trình C Cơ Bản - VnCoder
-
[PDF] Bài 2 C/C++ Nâng Cao - Soict
-
Các Phép Toán Trên Con Trỏ
-
Con Trỏ Và Cấp Phát động Trong C++ - TMA Solutions
-
Con Trỏ Trong C - Học Lập Trình C Online - Viettuts
-
Con Trỏ Và Mảng Trong C++ - Học Lập Trình C++ Online - VietTuts
-
Toán Tử Trong C++
-
Con Trỏ Trong C++ Là Gì
-
Con Trỏ (pointer) Trong C++ - Thủ Thuật
-
[PDF] Bài 10: Con Trỏ Và Mảng động - VNU-UET
-
Con Trỏ Trong C/C++ - VNOI